Skip to content

Latest commit

 

History

History
229 lines (187 loc) · 10.9 KB

README.md

File metadata and controls

229 lines (187 loc) · 10.9 KB

Unity UI Optimization Tool

A Unity Editor tool that automatically optimizes selected UI game objects (including Prefabs) to save you time.

Made With Unity License Last Commit Repo Size Downloads Last Release

🖥️ How It Works

For starters, import the package located in the Releases section into your project.

Now then, inside the Unity Editor, select any number of game objects anywhere: in the scene's Hierarchy, in the Project window or in Prefab Edit Mode.

Next, go to Tools > JGM > Optimize Selected UI GameObjects and press it.

It will automatically optimize the selected game objects (including Prefabs) with the supported techniques.

🛠️ Unity UI Optimization Techniques

🛠️ Using more Canvases

Using more Canvases

Every time a single UI element inside a Canvas changes (e.g. change 1 Text or Image), the whole Canvas has to generate the meshes and draw them all over again (very costly).

🛠️ Separating objects between static and dynamic Canvases

Separating objects between static and dynamic Canvases

  • Static Canvas: contains UI elements that are never going to change; good examples of these are background images, labels, and so on.
  • Incidental Dynamic Canvas: contains UI elements that only change in response to something, such as a UI button press or hover action.
  • Continuous Dynamic Canvas: contains UI elements that change regularly, such as animated elements.
🛠️ Disabling Raycast Target for non-interactive elements

Disabling Raycast Target for non-interactive elements

For all Image components that are not part of a Button, disable the Raycast Target (basically disable it in all images except for buttons).

Each time there is a UI input (click, tap, scroll, etc.) Unity's GraphicsRaycaster iterates over all the Raycast Targets in the scene, so the less we have the more processing we save.

🛠️ Hiding UI elements by disabling the parent Canvas component

Hiding UI elements by disabling the parent Canvas component

To avoid the Canvas regeneration, it's good habit to split the UI into different Canvases, and instead of disabling a LayoutGroup, disable an entire Canvas.

🛠️ Avoiding Animator components

Avoiding Animator components

Unity's Animator components are meant for 3D avatar animations primarily. Using it for UI elements causes extra processing.

Instead, the best approach is to use a custom tweening tool such as DOTween.

🛠️ Explicitly defining the event camera for World Space Canvases

Explicitly defining the event camera for World Space Canvases

Always set the Event Camera in a World Space Canvas as if there is no Camera assigned, it will call FindObjectWithTag("Main Camera") on every single frame! ☠️

🛠️ Don't use alpha to hide UI elements

Don't use alpha to hide UI elements

Even though the Image's color property is set to alpha 0, it will still cause a draw call.

Instead, disable the game object itself, or set the alpha of a Canvas Group to 0. This will prevent any draw calls from this object and its childs (0 draw calls).

🛠️ Make sure to use a RectMask2D

Make sure to use a RectMask2D

Like this, any element that is not inside the Scroll Rect, will not be drawn saving plenty of draw calls.

🛠️ Disable Pixel Perfect for ScrollRects

Disable Pixel Perfect for ScrollRects

Pixel Perfect makes UI elements appear sharper, but since in a Scroll Rect there's going to be movement, we won't notice it and we'll save a lot of processing.

The Scroll Rect should be on a separate Canvas with this setting off and other UI elements appearing in the same screen, would be in another Canvas with this setting on.

🛠️ Manually stop ScrollRect motion

Manually stop ScrollRect motion

We can use ScrollRect.StopMovement() to stop the motion once the ScrollRect.velocity is below a certain threshold to reduce regeneration frequency.

🛠️ Using empty UIText elements for full-screen interaction

Using empty UIText elements for full-screen interaction

For a Button that's going to be interactable full-screen, for the Button's Target Graphic, don't use an Image that fills the whole screen and has a color alpha set to 0 (as transparency breaks batching processes).

Instead, for the Button's Target Graphic, use a Text with no Font or Text defined.

🛠️ Reduce Game Objects inside Prefabs

Reduce Game Objects inside Prefabs

Wherever possible, try to reduce the number of game objects inside of a Prefab, maybe in some occasions it's possible to merge 3 game objects with Images into 1 single game object with 1 Image.

🛠️ Avoid Layout Groups when possible

Avoid Layout Groups when possible

Whenever possible, try to avoid using Layout Groups, specially nested Layout Groups, as it's very costly performance wise.

🛠️ Adjust texture compression formats

Adjust texture compression formats

Always adjust texture compression formats for your UI Sprite assets, to reduce memory footprint. Available compression types can be found here.

🛠️ Use Sprite Atlases always

Use Sprite Atlases always

Use Sprite Atlases for grouping single Sprites into one big texture to reduce the number of draw calls.

🛠️ Take order into account to prevent Batch Breaks

Take order into account to prevent Batch Breaks

Order in UI hierarchies matters. If you have in a hierarchy this order:

  • SpriteA1
  • SpriteB1
  • SpriteA2
  • SpriteB2
  • SpriteA3
  • SpriteB3

(meaning 'A' Sprites are from a specific Sprite Atlas and 'B' Sprite are from another one) it will issue 6 draw calls because the batches are breaking as all Sprites from one Atlas are not consecutively in line. To prevent this Batch Break, order them as in:

  • SpriteA1
  • SpriteA2
  • SpriteA3
  • SpriteB1
  • SpriteB2
  • SpriteB3

As a result, this will only issue 2 draw calls.

🧰 Tool Supported Techniques

Disabling Raycast Target for non-interactive elements
Avoiding Animator components
Make sure to use a RectMask2D
Disable Pixel Perfect for ScrollRects

📚 Bibliography