My game dynamically loads and creates sprites. However, if there are more than two sprites used in the game, the drawcalls continue to climb ever upwards, essentially one for every other sprite, roughly.
I have a tiny little demo of the problem attached here. Run the DemoScene scene and look on the 0scripts object for a boolean toggle box to show/hide the problem.
When more than one possible sprite is added to the “possible sprites” list, the drawcalls spiral endlessly upwards. When I choose only one possible sprite, then the batching occurs as normal, up to the batch limit.
What is going on here? What am I doing wrong? My entire game will probably have only five or ten sprites, and yet the way this is working, almost every instance of them has its own drawcall, and I intend to have hundreds of the same copy onscreen at once.
I’m using UnityPRO, I have sprite batching turned on in the Editor settings, and I have an identical sprite packing tag string set on the two sprites.
I figured out what is going on here, but it seems really limiting as far as Unity’s 2D engine goes.
My ever-spiralling drawcalls seem to have to do with the .sortingOrder field on the SpriteRenderer. Apparently Unity has to make a fresh drawcall whenever the sprite variant changes, even if the sprite is (supposedly) backed into the same sheet. Why is this?
To demonstrate this finding, see either scene in the updated project attached below. I renamed the original scene and added a few more tweaks and twiddles, but the tl;dr is that now you can toggle on/off an option to put each sprite variant into an explicit .sortingOrder.
Am I reading this behavior correctly from the above experiments? Or is something else at work here?
This seems a bit limiting and counter-intuitive to the whole point of batching or atlasing. How can we avoid having to think about .sortingOrder relating to drawcalls on a supposedly-batched sprite? This seems needlessly brain-dead when you are trying to just focus on making a game and don’t want to have to worry about the underlying implementation so much.
I tried to play around with your example and see where the problem can be fixed, but I really don’t get why is adding so much drawcalls, there is nothign wrong in the code. I tried also to assign the sprites to a public list in the inspector and read from there, but still keep adding drawcalls.
I believe there is a problem with SpriteRenderer itself, not on your side, but on unity side. Because I tried this for the game object creation part:
for( int i = 0; i < 10000; i++)
{
GameObject o = new GameObject();
if(!o.GetComponent<SpriteRenderer>())
o.AddComponent<SpriteRenderer>();
SpriteRenderer sr = o.GetComponent<SpriteRenderer>();
sr.sprite = sprites[ Random.Range ( 0, sprites.Count)];
o.transform.position = new Vector3(
Random.Range( -size, size),
Random.Range( -size, size));
yield return new WaitForSeconds( 0.25f);
}
This way drawcalls still raise, but after 2 or 4 objects created, which confuses me even more.
I even tried freezing the material from the first time I make a particular variant of a sprite and then recycling that material into subsequent sprite instances, but still the same ever-climbing drawcalls. It’s a bit disappointing this doesn’t just work and it really does “smell” like a Unity bug.
I’m pretty sure is a bug, I did a dynamic sprite system a while back for my game, all worked good, so I didn’t bother much to recheck drawcalls and that was before the new UI, so maybe this bug or whatever may be introduced after the UI stuff.
Thanks Neuro, there’s a ton of other google-able results for this but nothing that says “this is what you’re doing wrong, don’t do that, do it this way.”
All results either insinuate this is a unity bug or else the posters never followed up. If I don’t hear otherwise I’ll go file a new bug, but with the IL2CPP fixes in full swing, I’m not hopeful it would get much priority right now.