Batching Sprites in 2D - "Objects have different MaterialPropertyBlock set"
I've been running the frame debugger on my project as rendering takes the largest chunk of performance. It is a 2D isometric game, where a procedurally-generated forest of overlapping trees is rendered. (Image attached)
To try and improve the performance I've already tried the following:
Added everything to the same texture atlas.
Using the unlit/cutout shader for textures.
Using tight meshes for sprites.
Removed all transparency from sprites aside from 0% alpha surrounding tiles
Set objects in the scene to be static (although I believe static batching isn't possible with sprite renderers? Can't find confirmation of this...)
I'm still seeing huge numbers of separate dynamic batches being rendered in the frame debugger, with the issue: "Objects have different MaterialPropertyBlock set" (image attached, 1 of 400 draw calls).
Every object in the scene just uses a sprite renderer with the same material, but a different sprite.
Pretty stumped as to how to reduce the number of batches. Each tree sprite on each row has it's own batch, which I'm sure could be reduced somehow.
Hey @bwimsett , did you ever figure out a solution to your issue? I'm having the same issue, albeit a different scenario.
PS: Love your videos on Lumbermill, best of luck with it all!
Answer by Pangamini · Mar 16 at 03:29 PM
The materialPropertyBlock message is a bit cryptic, but I think i figured it out. I've noticed, in my project, that if all my sprites are using the same spriteAtlas, then they get batched correctly, but not otherwise. If you think about it, it makes sense. Sprites use alpha blending and rely on draw order instead of depth test. Since they are using sprites from a different atlas, they cannot use the same material without at least using a different texture, set using a materialPropertyBlock. I've noticed that sprites that use the same atlas and stand close to each other get batched properly. Then the texture has to be swapped to new atlas. You can try and use an opaque shader that is not sorted. I've observed that now all sprites are batched per atlas instead of per intended rendering order - which, since the sprites are not actually utilizing the z-test in any way (they all sit in the same 2D plane) leads to incorrect results.
So, you could:
Put all your sprites in a single texture of an atlas (test in play mode)
Use opaque shader, but make sure that the sprite's overlapping depends on depth instead of render order
If you are making a mobile game, it's probably better to just sacrifice the batching rather than disabling tiled GPU optimizations by using alpha testing. I've been running a lot of benchmarks recently, and I've seen barely any effect of batching or its absence on mobile devices, including instancing and SRP batcher