I have some world geometry that I want to change the colour of regularly e.g. say I have a building that’s usually grey but when a green player occupies it, the building turns green (a team colour).
This would be quite frequent so I would like to know if I should be using a shader to change the colour, or continually swapping out/changing the mesh’s colors array?
e.g. with a mesh colouring
buildingGameObj.GetComponent<Mesh>().colors = greenTeamColours
or by changing parameters in the shaders?
buildingGameObj.renderer.material.SetColor("_Color", Color.green);
…assuming the shader attached to the material is using a _Color param.
The more I think about it, this seems like a dumb question, but I haven’t done much shader programming and want to know if shaders are the most efficient way to implement something like colour changes.
Somewhat related to this, if the shader is responsible for setting colour, why have a Mesh.color array at all? I notice that if I leave it out, the shader does all the work.
Thanks.
The more I think about it, this seems
like a dumb question
It is not a dumb question, and the answer is somewhat involved. First the Mesh.colors array set the vertex colors. Only a fraction of the shaders that ship with Unity support vertex colors. Vertex colors allow you to set colors on individual vertices which in turn allows you to set the color for individual pieces of a mesh. If vertices are not shared, using vertex colors allows you can set the color on individual triangles in the mesh. So in your case, you potentially could set the color of the roof of the building without setting the color for the whole building.
The _Color is also only supported by a fraction of the shaders that ship with Unity. Most shaders that use this color, implement an overlay color, but nothing says what the shader should do with the color. It is just a property that a shader can use however it wants. I suppose the same can be said of vertex colors…it is up to the shader how it wants to use the information.
Before I compare and contrast, a brief note about drawcall batching. If two objects share the same material, and if the two object have less that 900 total vertex attributes (usually means 300 or less vertices), then those object can be sent to the GPU in a batch. Batching game object together can have a substantial, positive impact on performance…especially for mobile devices.
So back to your question. Whenever you change any property of a material, Unity gives you a new material instance, and that game object will no longer batch. So using _Color will break batching. So if you had a bunch of simple buildings (300 or less vertices), each time you set the _Color properity on a new building, your drawcalls would go up by one. By contrast, setting the Mesh.colors will not break batching, so you could change the colors of individual buildings without suffering an increase in drawcalls.
Summary:
- Simple game objects that batch → Use Mesh.colors
- Objects where you only want to change the color on part of the mesh → Use Mesh.colors
- Complex objects that do not batch → Use _Color