I’m a bit confused about how to minimize the draw calls. I have a game where there are lots of blocks that have varying colors, but still a limited set of colors, but otherwise sharing a similar material. So, which of these three is true:
A) I can reduce draw calls to 1 for all of the blocks.
B) I can reduce draw calls to 1 per each block color.
C) I can’t reduce draw calls, but have to have one draw call per block.
D) Something else between A and C?
Of course best would be A, but that’s not possible, I guess? Well, the thing is that for some reason even if I make all the blocks use the same sharedMaterial, in which case changing the color of one block will change the color of all the others, the draw call count just keeps rising when more blocks are added. Why is this? All I do is Instantiate and set a new local position. I don’t even manipulate the scale, which I’ve understood could cause draw call batching to not work.
I’m not entirely sure how or why, but my (relatively) simple scene was getting 2000+ draw calls on the Forward renderer. Switching to deferred lowered it down to 32. I don’t know if I just don’t understand how it works completely, or if batching is broken on the Forward renderer, but it works fine on the deferred renderer.
As for batching, it really help if they are the same material. Not “almost” the same material, the very same material. You can probably reduce to a single draw call for all the blocks if you can get them onto the same material. Look around on the forums for a standard shader that accepts vertex color. Or, alternatively, pack textures of different colors onto the same texture and have each block have a slightly different UV set. Since they have a shared material you obviously can’t change the color of the material, you’ll have to use vertex colors or UV sets to change the color on a per-block basis.
If the material has a shader that’s too complex, it doesn’t help. I had exactly the same material that was shared between them, but the shader selection prevented batching. But by using VertexLit, it was pretty easy to just set each color have their own material and share that between blocks of same color.
Thanks for the link. I don’t think it exactly matches my need though. In a way my need is more simple as I don’t need to combine different kinds of meshes together for this, but on the other hand I need to be often removing and adding elements so merging meshes all the time wouldn’t probably be that good either. I do have some of my own mesh combining logic for optimization purposes for some other parts of my small game, but it doesn’t look like I’d need that for this.
Changing to VertexLit seemed to work nicely for my purpose:
Draw calls got down by batching (one per color).
I could use the various colors.
Things look alright in Unity Editor.
But now there is still a problem: when I play the game on iPhone5 the materials flicker in a really annoying way. Why is that? iPhone doesn’t support something? What kind of shader should I use so that:
Any help with this? I’ve dug the documentation and tested with the more simple shaders, but none of the “mobile” ones offer the option of adding main colour, so the only option of the built-in shaders seems to be VertexLit, but for some reason it has a weird disturbing flickering effect in the game as if the game couldn’t decide whether the object is lit or not. This effect never occurred until I changed the shader to VertexLit.
So: is the way to go make my own shader for this then? Or is there some way I could try to make the VertexLit not cause that annoying flickering?
Are you sure its the shader causing the flickering and not the use of dynamic batching with that shader? I seem to have a vague memory of seeing something similar once and it was the use of dynamic batching at fault. Of course if true that doesn’t help you since you need the dynamic batching.
As to your original question it should in theory be possible to have a single draw call for all your objects if the main difference between them is just their color by switching over to use vertex colors in the mesh/s. Vertex Colors are not the same as vertexLit shader, they refer to adding a colour per vertex in the mesh. This can be done either programatically or via your modelling app. You will need a tweaked shader for this to work, one which can read and use the vertex colours, but you should find plenty of threads and examples in the forums for that and maybe even in the Unity documentation on custom shaders.
So since the material/shader is now the same for every object and doesn’t even change the shaders ‘main’ color Unity can now dynamically batch them all to one draw call. Whether or not it will actually do this depends on other aspects, but it should reduce both your drawcalls and setpass call further ( Unity 5.x switched to showing the difference between setPass and drawcalls, setPass calls are ones that take the most time, but drawcalls are still not free, so eventually too many will still cuae problems).
Now the bigger question becomes is Unity dynamic batching actually more efficient for your case? In many instances it will be, but as it dynamically batches objects every frame that takes time and thus there may be cases where its no better or worse than just having many drawcalls ( especially as Unity 5.x optimized to reduce pointless setpass calls). There are no hard rules to give you here, as there are simply too many different variables to consider, from the number of batched objects to the platform you are targetting. In the end the only way to know is to test.
At which point you come back to suggestions like that in the thread theANMATOR2b posted above and for taking control and building combined meshes of your objects yourself in order to maintain a greater degree of control over the generic Unity systems.
Thanks for the elaborate answer! No I am not sure, if it’s the shader or dynamic batching combined with that shader. What I do know though is that I found that Self-Illumin/VertexLit allows me to do dynamic batching without that flicker - the problem with that is that for some reason the materials then appear depressingly dark on mobile even though in Unity editor they appear bright, like I want them to…
Thanks. Yeah, probably that is somehow possible, and maybe even so that it would increase performance, but that wouldn’t be worth the trouble as I only have 8 colors ( = only max 7 draw calls to save) - not to mention the uncertainty of the actual performance increase.
Yeah, that has occurred to me too: is draw call reducing by far the most important thing in general or not. I’m using Unity 4.x though. I’m targetting mobile - iOS primarily, and then android. In my case whether the dynamic batching is in place for the material I’m concerned about in this thread, defines whether the draw calls are at the range of about 60-70 or whether they can rise up to, well, something more like 160-170. So my guess is that it would be pretty useful to get batching working there. I just don’t know how to test the performance well numerically. I mean even if I could get some kind of picture of performance change on a laptop or desktop computer, does that necessarily mean that difference would also apply to mobile?
VertexLit and Self-Illumin/VertexLit have gotten me close. If I’d just get something similar that wouldn’t appear so dark and wouldn’t flicker, I’d be happy.