I need a hint on draw call and batching. I don’t understand why dynamic batching is so bad.
My 2D sprite game is idle bullet hell. The player is in the center of the screen and hordes of monsters are running to him. (clone of Vampire Survivor)
Monsters are SpriteRenderer, sprites inside SpriteAtlas.
300 monsters are rendered in 3 rendering calls (about 100 monsters per draw call) - this is more than fine for me.
But when I added blood particles (Particle System, just Texture Sheet Animation block, material with shader Mobile/Particles/Alpha Blended, take particles from pool and setted inside monster game object when damaged), the situation worsened dramatically.
Frame Debugger say Batch cause: Objects have different materials.
Now there are an average of 200 rendering calls - the rendering of blood particles is wedged between the rendering of monsters.
My expectations: monsters will also be drawn in 3 events, and then renderer blood (preferably in 1 call, as with the shadow, but not metter, event 1 event on 1 particle).
But not as much as 200 events on average.
Can you tell me why dynamic batching does this: why does it draw blood between monsters and cut rendering calls monsters into such small pieces? Why not draw the monsters first, then blood.
I am glad for both practical advice and links to theory.
This may have to do with sorting layers. If you child a particle effect on a sprite I guess this defaults to render the particles at the same layer as the sprite.
If the renderer would draw monsters first, then particles, the particles would all be drawn atop of all sprites. This may be unexpected.
Try for a test to set all particles to be rendered atop of all other sprites.
You should also try not parenting particle effects to sprites but rather have them follow their target but be placed on a different object.
It seems ‘Objects have different materials’ is worth further inspecting, if the goal was to have a common material. You may also want to check Unity - Scripting API: Material.renderQueue
Particle Systems can be dirty liars. The material can appear the same but its properties are not when compared to a Sprite Renderer.
****
As CodeSmile said, set it to sort consistently on top.
But it’s even more performant if you fuse the sysems together into one. Then you use particleSystem.Emit, though it’s a little more work to set this up.
Another option for certain situations (probably not here): convert the particle blood to be pooled SpriteRenderers that have the same material as the monsters.
You mean one particle system for all blood splatters and the same system just emits particles at different locations, and with separate start/stop times? Interested in hearing more about this since I want to use particles in 2d soon for practically the same purpose.
Yes, that’s exactly what I mean. You can load a lot into the EmitParams, then particleSystem.Emit it with unique position, direction, color, etc. You can also not specify as much and* it’ll pull from what you have set up on the component.
The key thing to keep in mind is that you now only have 1 sorting position so it can’t do everything, especially if everything is transparent as is usually the case with 2D.
To add to this, this situation is specifically needed for when you HAVE to have individual sorting of each pseudo-particle (Sprite Renderer) in a 2D transparent world. It’s less performant so you do this for visual quality reasons.