Unity’s UI batching system always felt like a big unknown part of the engine which nobody really could demystefy for me. I’ve spent the last year creating a lot of tools for the UI, finding classes like UIBehaviour or IMeshModifier which you only need in very specific cases. But for being able to provide efficient tools, you first need to know what impact your tools have on the product. And if you figure out the most likely case that it runs very poorly, you need to find a way to improve it. For that purpose, the guys from Unity provided us with pretty good tools, like the UI Profiler.
It even tells you what the reason is for batching being broken. And it tells you what gameobject are included in a batch. So that’s pretty handy, but sometimes you look at a material which is used by two different GameObjects. They are both sharing the same SpriteAtlas and it breaks batching. A case where it’s really hard to figure out why this is. Or you look at a ton of GameObjects which all use the same material with the same Sprite but they can’t be batched. All these are cases where the information from Unity are not sufficient to re-enable the batching. That’s why I’m here for you giving you some advices.
One of the most important reasons batching is broken because 0f one GameObject using a different material in between of several GameObjects which use the same material.
Imagine the following order of GameObjects being parented under exactly one Canvas.
“Hello”, “Name” and “Stefan” are using the same material A (using Texture A and the Default UI Material). The second batch consists of “My” and “Is” which are using a different material B (using Texture B and the Default UI Material). This whole UI wouldn’t be batched at all because of the order they are in. That brings us to lesson number one : order matters. A lot. Changing it to this would fix it.
What bothers me having such an easy way to fix is that sometimes it is just not possible. Imagine you have a vertical layout and doesn’t work in any other order for you? What are you gonna do? There are some ways which work. Having both textures in one SpriteAtlas is one solution solving this. But only if they are one the same atlas texture. It can easily forgotten that if there are too many textures for one atlas page, it creates a second one internally. Having them being spread across two textures breaks batching again, even if you didn’t mean to split them. So keep that in mind when determining which textures goes on which SpriteAtlas. Sometimes you just want or need to split them up. Memory handling is a key part of every game. You want to have as little chunks of your UI Textures as possible lurking in your memory.
Another obvious reason for batching to be broken is that you just need an additive Material instead of an alpha blended one from time to time. Or some other effect to create a more sophisticated UI. Depending on the amount of additional calculations you intend to add, you might want to think about creating one Uber-Shader which handles most of your problems, making it easier to not break batching by reusing only material across most of your elements. Just start off by using Unitys Default UI Shader , strip off the elements you don’t need and add your own features.
A nuisance which you can hardly avoid and which is gonna keep on hunting you is the internal material of the Unity Text. There are two ways to solve this: find a way to reorder you UI to queue up all texts which frankly is in most of the cases unlikely. Second way is to create an image of your text and put this instead. This can become the hell of every QA engineer because let’s be honest, when it comes down to localization and iteration, you need to be quite quick. So this requires smart adaptable tech to be an option if at all.
I hope this gave you a good overview about some of the things to think about when creating your next Unity UI. Thanks for giving it a read!