UI batching in Unity
Updated 2 years ago
Learn more about how Unity's native UI system works
There are several things that need to be taken into account when building your UI and if you want to learn more about how Unity's native UI system works, read on.


The main thing the Canvas does is to batch elements together. Batching means that it takes all the same elements, that have the same texture and material, and tries to put them in 1 draw call if it can. If it can't do that, it creates more draw calls and the more you have, the less efficient your UI design is.
What does 'the same texture' / 'single texture' mean?
Images use sprites that, by default, get packed into an atlas. That atlas is that single texture. So if the sprites used in your UI are on the same texture, and you did not override the material, you get 1 draw call (this is very important for optimization purposes).
Text, on the other hand, is always in a different atlas. So if you have an Image followed by Text , you'll have 2 draw calls as they cannot be batched together.
The batching system used by the UI has been thredded since version 5.2. This means that all the sorting code has been split into quick little threads that execute when there is time (so that they don't block the main thread).

BATCHING - Overview

1. GenerateRendableUIInstructions
- takes all the Canvas Renderers data and copies it (because of threading).
- figures out what instruction can actually be rendered;
----- is the alpha zero? (if yes, it is not added to the render as there is nothing to render)
----- is the size zero? (if yes, it is not added to the render as there is nothing to render)
----- has it been called by a RectMask2D? (is it outside of the culling area? - if yes, then it gets dropped)

2. SortForBatchingJob
- here all the batching stuff gets sorted into 'buckets'
- once the order has been calculated it starts preparing for the batch jobs

3. PrepareBatchesJob
- this is actually preparing the rendable UI instructions to be passed to the graphics device for a little bit of processing

4. UIGeometryJob
- this transforms the vertices, modifies colors and applies lighting (if necessary)

Once the UIGeometryJob finished, one of two things happen:
1. If it's an Overlay canvas, the canvas renders the data directly to the graphics card itself (at the end of the frame, after everything else has been drawn)
2. The Screen Space Camera and World Space canvases, insert themselves into the camera's render queue and gets further processed to be sorted with all the other world geometry that you have.

HINT: If you don't need lighting, nor particle systems inside the UI, the Overlay canvas is the fastest option, as you don't have to wait on anything else. Unity is not doing any extra processing on it.

BATCHING - Sorting Buckets

Each grid 'square' is considered a bucket. When processing the sorting and going through all the rendable instructions, they system needs to figure out in how many buckets an Image (for example) can be put into. If an Image spans on 3x4 grid squares, it will be split into 12 different buckets.
If there are several 'items' in the same bucket, extra processing occurs. The depth is calculated (sorting order).

BATCHING - Common Issues
Elements are not aligned
- look at the z axis; you should use the same z; not having the same alignment, causes a break in the batch because it messes up the draw order and significantly increases your batch count
- this can be seen in the draw call count (or the debugger); so this is a huge optimization that you need to be aware of
- easy solution to this -> select all your UI and put it on z = 0 or any other value, just have your entire UI on the same z !!! -> Done

Sprites are not sharing the same texture
- so they are not batching together
- check that your sprite atlases are turned on
- check that you specified the same packing tag for all of your sprites used in the UI
- make sure you have the same settings for the sprites (for example one can be on mip maps and the other is not); if the properties do not match, you'll get different atlases; so just check your import settings (for your ui graphics) and make them all the same so that they can be batched together

About the canvases, you should know that when a child of a canvas has its properties changed (for example a
RectTransform's values, or maybe an Image's color), that entire canvas needs to be 'refreshed'. So if you use one big canvas for your entire UI then you are doing it wrong. Every time you press a button, or change anything to it, your entire UI will get refreshed. Imagine having an animated sprite inside that canvas; that would trigger a constant refresh for your entire UI. So split your UI into different canvases and increase your UI's performance.

The Graphic Raycaster works hand in hand with the Canvas component. It is used to capture clicks/touches for the UI. If you have several stacked Graphic Raycasters, only the top one will get triggered. It is quite efficient, if you use override sorting, because if one Graphic Raycaster 'is triggered', all the others are not checked (ignored) on that frame. This is useful especially for buttons, or to block clicks/touches on the UI.

I hope that by reading this quick introduction, on how the batching is done inside Unity, you will have a better understanding of how to structure your UI in a more efficient manner.
Alexandru Mares
Doozy Entertainment - Owner