Do you know what batching is? You may want to check out the Nvidia presentation Batch, Batch, Batch for some more details but long story short, batching the graphics data means to wrap it up into a single package and send it to the GPU in a single pass. Why does that matter to us? That’s because when we’re dealing with mobile devices we are seriously limited on how many of these packages can we send per second. And there’s something we can actually do about it!
What is batching?
What is batching? Imagine you’re doing some weekend’s shopping. You’re buying milk, bread, butter and you go to the checkout. You have just paid and the phone rings. You answer and you hear:
I’m sorry, I forgot to tell you that you need to get some eggs. Are you still in the shop?
A bit irritated, you put your things into the car’s trunk and you’re back in the shop to get the eggs. When you’re done with the checkout, you hear the phone ringing once again:
I’m really, really sorry, but can you also get some tomatoes?
OK, that what the batching is not.
When you put a mesh object into your scene, you’re saying to Unity: „Hey, draw for me a car mesh here and use this material that I gave you!” and Unity will listen. It will:
- Read all vertices including colors, uv, normals, tangents etc.
- Read the material shader, texture.
- Speak with the GPU: „Hey GPU, please use these vertices, this shader and those textures for the next object!”
- And the GPU does as told.
Then you decided to put the same car mesh next to it. By doing so you’re saying to Unity: „Hey, could you draw the same car mesh with the same materials next to it?”. Unity won’t complain and it will do it too, but how exactly? Do you see that this situation is similar to previous shopping example?
How Unity knows what to batch?
Since Unity is a well designed engine, it does not start any rendering before you decide what objects should be included into the scene and what not. You can make the decision in every Update(), FixedUpdate() or LateUpdate() function by changing objects positions or enabled state. You can learn more about the frame execution order here.
When Unity knows exactly what should be rendered, it creates batches. A batch is a package with data that will be send to the GPU. Usually, the fewer packages there are, the better. But Unity cannot pack everything into a single batch. It can batch together quite large amount of geometry vertices, but it can set the material only once per batch. This means that it can batch objects only with the same material. Here’s our car mesh example that will batch:
Now Unity will do the following:
- Read all the vertices (that’s not entirely true, but let’s imagine it that way).
- Read the material shader and texture.
- Speak with the GPU: „Hey GPU, please use these vertices, this shader, those textures and draw it here and there!”
- And the GPU does as told.
Practically Unity just rendered two objects with the cost of one. How cool is that?!
How to prepare the scene?
To make batching work you have to prepare your scene objects in a specific way. First, you need to know that there are two kinds of batching methods in Unity. First, there is a…
This is the simplest possible batching done by Unity. All objects that may be batched dynamically should share the same material (copies of the same material do not apply) and fulfill the following criteria:
- Mesh should contain less than 900 vertex attributes per total. For instance, if shader uses vertex position, normal and single UV, then you can batch up to 300 verts.
- Object should be using the same transform scale.
- Object is not lightmapped or is pointing to the same lightmap location.
- Material is using single-pass shader.
- Object is not receiving real-time shadows.
On the other hand, static batching allows the engine to reduce draw calls for geometry of any size. The requirement about the material still does apply and you need to make sure your object will not move by making it static.
Static batching will require more memory than dynamic batching, but it does not require any additional CPU power to do the batching.
More details about those batching methods you can find in Unity documentation.
There’s little you can really do to find out why batching is not working as expected until you’re aware of the rules above. Then you can check how many objects have actually been batched. One way of doing so is by using the Stats window in your Game view.
There are two entries that we want to look at:
- Batches – this is the total number of batches used to draw the scene that we’re seeing.
- Saved by batching – number of batches that were merged into other batches.
So without batching this scene would need 12 batches to draw. Remember: the lower, the better!
Please try to open the Profiler (Window -> Profiler or Ctrl + 7). Run your game and then:
- Click on the Rendering section
- Look at the bottom part of this window.
Profiler will be a little more descriptive about what kind of batching has been done, about the number of batches and the number of tris/vers that has been batched in total.
The Frame Debugger is something that can be found only in Unity 5 (and most probably above) and can be opened through Window -> Frame Debugger menu. Frame Debugger allows you to:
- Traverse through all the batches and see what is rendered on the scene after each batch.
- Locate the actual batch to see what is batched and to verify what may be breaking it.
Batching is very important part of making your mobile game animation smooth; ignore it and you will suffer the consequences. You may be curious about reasonable upper limit of batches that your game can produce. From our experience it can be around 150 to 300 but it depends on used shaders, fill rate, vertex density and used Unity version (not mentioning the device performance of course).
This is not everything that you can do about mobile games optimization. You will find more entries of this series in the future. Make sure you click on the Mobile Optimization tag to find all of them!