gonzokawasaki - you’re not really locked down to anything, stuff like optimising draw calls is just something to keep in mind. (so you don’t make decisions early on that will bite you later, like building characters that each use 37 separate materials)
If your scene is modest enough it won’t really matter how you construct it, but when you’re trying to get performance out of your game or track down why it’s grinding to a halt, these things are good to know.
Ok, sorry for the necro-thread-ing, but I’m looking for a bit more informations on this :
I’d like to tweak @yahodahan_1 's example to make sure I’m going for the right solution :
What if, in Scene A & B, we are using the same Shader for all the meshes, but for Scene C, we use 6 different shaders? Is C still a better solution?
And, so that I would fully understand the answer, do Shaders have an impact on draw calls (or rather “batching”, as it is the actual thing you want to reduce) or on the overall game performance? Thanks for your answers
EDIT : my bad, I was mislead into believing that I could have a single material with different shader while in reality, that would force me to create different materials…
Draw calls are not a major performance issue anymore as long as they’re not excessive, Unity also batches draw calls and you can set up your scene carefully to take advantage of this (for example all of those trees are batched) and having materials is better visually because it allows you to change the material properties on parts of the model like seen above.
I consider assets that have flat shading with a texture to be very low quality, because the texture then takes up a lot of memory and it’s completely wasted. I would strongly recommend using separate materials to handle your mesh.
Not to necro a slightly old post, but someone mind explaining why this might be the case? AFAIK unity doesnt batch drawcalls unless sharing the same material.
In the case of flat shading (like in the image) it would seem pretty obvious to use either vertex colors or an atlas with small squares (color samples). Am I wrong?
Edit - I’m assuming he’s referring to SRP batching in the LWRP. Would be interesting to know the performance difference between atlasing and just using multiple materials with the same shader.
For people who care, I did a small test on android/phone.
With a grid of houses, each house either using … 1 material + 512 diffuse or 4 materials using a 256 diffuse each.
Difference was like night and day. Looking at the frame debug, the SRP batching seems to be working fine. Looking at the fps though, I’m getting around 14ish fps with the multi material setup versus around 50+ with a single. SRP is enabled in the SRP config. This is using raw models, no LODs.
With numbers like this, it almost seems as if SRP batching isn’t working on mobile (or I’m doing it wrong).
Edit - BTW I’m using the “simple lit” shader for all the mats, which should support batching.
I apologize if it seems I’m spamming the thread, but this has quite large implications on my asset workflow.
So far I had been testing single meshes with either one or multiple materials (with or without LODs). What I didn’t test was having a ton of single material meshes with different materials on each and to my surprise it made a big difference, to the point of looking similar to using the same material across all.
Inspired by this I tried splitting the mesh based on material use (still one fbx, just multiple meshes), but it didn’t increase performance a lot.
So from what I can tell, it’s ok to use different materials (don’t need to atlas everything into one), however referencing multiple different materials on the same mesh should be avoided like the plague.
After a lot of testing, vertex colors are the best way to achieve this look with maximum speed efficiency! This allows the entire object to be batched as one piece.
When we are talking about batching, are we talking about toggling the “Enable GPU Instancing” option in the material? Because that can also significantly improve your performance for materials that you might see a lot from a single camera position (e.g. those trees and cars.)
If you want to know if your batching is actually ‘working’ (This one’s for you Ng0ns) you can open the ‘stats’ bar in the game window and look at “Saved by batching”. Check it the next time when you’re not sure.
Batching refers to two processes: static and dynamic batching. GPU Instancing is related to batching in that it is a method of reducing draw calls, however it is more restricted and has higher performance gains. It works by storing the mesh on the GPU once and then drawing it repeatedly in just a few draw calls to fill out the scene. It’s an extra feature that has to be added by the graphics programmer or you need to use a shader which supports it, such as the standard shader.
Static batching occurs when you mark your GameObject as “Static” in the Inspector. When you do, Unity builds it in to a large data structure with the rest of the static scene geometry to increase the render efficiency.
Dynamic batching occurs when multiple instances of the same mesh appear on screen, Unity will try to draw them all at once to save draw calls. To make this happen more often, make sure that the meshes are not mirrored and have uniform scale, and that they have the same material applied to them.
You only need to worry about batching if you have very dense scenes with a large number of meshes. In that case, reducing the number of meshes is a good start. You can also reduce the number of texture maps, as each extra texture on a material adds another draw call or three.
The main issue is that different materials break the batching. The new SRP pipeline should help against this as it allows batching of different materials using the same shader, but this unfortunately doesn’t know for Android devices below Opengl version 3.1.
I’m unsure how people work around this, the difference is huge (was seeing a four fold performance difference just in my test scene using 4 materials). It would be a lot easier to use different materials rather than altasing into large sets (that doesn’t tile easily), but performance would be abysmal on lower end devices.
Damn. For the whole life I thought that A scenario will be way more preferable, compared to B in terms of performance. But I did a quick test and it seems that you’re right. Thanks for the info. You’ve saved me a ton of work.