Search Unity

How to use MaterialPropertyBlocks to randomly change the color of multiple materials on an object?

Discussion in 'General Graphics' started by the_mr_matt, Dec 1, 2016.

  1. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    I have a character prefab for a civilian with 5 materials. Each one should be a random color but I don't want a new material for every civilian in the game. I asked a question earlier and had a good answer. However I was pointed towards this question with MaterialPropertyBlocks. This is the code I currently have:

    Code (CSharp):
    1. public Color[] shirtColor;
    2.  
    3. void Start () {
    4.     Color newShirtColor = shirtColor[Random.Range(0, shirtColor.Length)];
    5.  
    6.     MaterialPropertyBlock props = new MaterialPropertyBlock();
    7.     props.AddColor("_Color", newShirtColor);
    8.     GetComponent<SkinnedMeshRenderer>().SetPropertyBlock(props);
    9. }
    It works really well but the color is assigned to the whole mesh. How can I do this for each of the 5 materials on the object so that it only changed the color for the assigned parts of the mesh, with only one material for each section?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,336
    Material property blocks are applied per renderer, thus if your character is a single mesh and renderer component you can't use a single color value to change the color of all 5 parts. To do it this way you would have to split up the character into 5 individual skeletalmeshrenderer components.

    That's doable, but just setting the color to each of the 5 materials would be faster both for setup and for rendering.

    There are of course other ways to do this. One option is to use a texture or vertex colors to mask different parts of the mesh instead of breaking them up into multiple materials, that way you can pass multiple colors to your renderer component using a single material property block and choose which color to apply where in a shader. An RGBA texture or the RGBA vertex colors are enough to easily have 5 colors, one color for each color channel and one more for all black. This is a technique terrain shaders use frequently.

    Alternatively you could just set the colors on the mesh's vertex colors itself using additional vertex streams and use that color in your shader.
    https://docs.unity3d.com/ScriptReference/MeshRenderer-additionalVertexStreams.html
     
    theANMATOR2b likes this.
  3. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    Thats perfect! I never thought about the idea of using a texture as the factor of the random colors to split it up the mesh without actually splitting up the mesh. Thanks!