Need a design advice (assets batching)

Hi guys,

so im currently working on a game which exposes a couple of design issues and i’d need some advice to manage the engine as better as i can.

The game needs to feature some character composition, so the player will be able to choose between several kinds of hair and eyes and so on like the Nintendo Mii for instance but using only sprites. (Well, just look at my avatar). Same for every npc.

Sprites need to be rendered with a diffuse shader to get affected by lighting.
Sprites need to be instantiated or associated with dynamic atlas textures loaded at runtime in order to avoid bad memory usage.
Sprites need to be grouped by their animation sheet, so for the same kind of hair the same sheet will share the run animation, the jump animation and so on. Or at least these are my organized assets so far.

Now the main issue is: batching.

I created a prefab with a parent GO and one child object for each separate face part.
Every object has a sprite renderer sharing the same material (i’m expecting to use setPropertyBlock to change shader params without instancing a new mat). But textures are different (because it has to take current hair from hair animation atlas, current eyes from eyes animation atlas and so on) so every child object makes one draw call and i can get it.

As you can imagine, populating a scene with 30 chars, if every char makes lets say 6 draw calls in total, means 180 draw calls only for characters.

And i’m asking how i could manage this in a better way.

Its really important to understand this:

  • Since i’m having a lot of atlas (each one contaning all actions per body part per kind, ie all actions for round face, all actions for square face, all actions for curly hair, all actions for straight hair, and so on), i simply cannot preload all of them in a scene. Best thing to do imho should be reading the atlas i’d have to load from character properties then load it dynamically to avoid memory bad consumption.

  • Since the chars number will be very different from run to run, i need prefabs to instantiate at runtime. This also because i’d need to compose characters using random at runtime.

  • Since the game will use directional light and lights in general, i need a diffuse shader to render sprites

With these premises, batching seems just impossible. I hope to find me wrong but i think there’s no way to load atlas dynamically and having instanciated prefabs at runtime containing sprites assigned by the loaded atlas, rendering all with a diffuse shader and getting all batched.

I’m sure i can achieve a good result in terms of performances but i’m asking you for the best pratices about circumstances like this one.

Thank you!

Here’s a quick reference.
“Saved by batching” on stats is referring to street so doesn’t matter at all.
Characters are the real deal, they’re 30 on screen now and they’re making >90 draw calls.
And eyes, nose, mouth and many other parts are still missing - this is gonna take a lot of more draw calls.
And i’m still using the same atlas for each single part of each character (same for all hairs, same for all faces and so on) but i’ll add more atlas to swap on in the future. As stated above, i’d need to load each character dynamically.
How can i save draw calls in this situation? Thank you!

Solved by batching by same material and organizing textures in a different way - using vertex color as a property for changing hue value of the shader was the key.

I can now handle as many characters as i want, everyone with a different face, with no extra draw calls, here’s a sample with 80 characters on screen.

However, i think Unity deserves a better batching tool for sprites and materials in general.

Thank you anyway guys. :slight_smile:

1 Like

@RavenTravelStudios hello how did you solve the matter of using the diffuse shader? if you add point lights doesn’t it break your batching? I’m having the same problem

Sure thing, i had to use not important lights to keep the batching on, but that was enough to my purpose. There are so many other things which tend to break the batching, like reflections or multiple pass shaders in general. What i’m doing on my project for each scene is essentially a work of balance between effects and objects on screen to keep it at high framerate.