Search Unity

problems with shared material and different colors

Discussion in 'Scripting' started by exiguous, May 25, 2015.

  1. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    TLDR how can I frequently color objects differently and still use dynamic batching.

    I have lots of colored objects on the playfield and thus want to use dynamic batching. When I use
    Code (csharp):
    1.  
    2. renderer.material.color = ColorManager.GetColor(colorIndex);
    3.  
    this works and each object has the color it should have but there are way too many drawcalls since every object has its own material instance.
    According to this documentation
    Then I gave ColorManager an array of materials whose color is set once in initialization. The idea is that each object is assigned a reference to a material so it has its desired color but the materials are shared between all objects of the same color.
    Code (csharp):
    1.  
    2. renderer.material = ColorManager.GetMaterial(colorIndex);
    3. // or with same result
    4. renderer.sharedMaterial = ColorManager.GetMaterial(colorIndex);
    5.  
    When I assign the material from the array to the material or shared material all objects appear in the same color (the last one from the array).

    So my question is if I'm doing something completely wrong or if the concept should work and I have a bug in my (complex) code. How can I assign an object a shared material of a certain color?
     
  2. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Have found a solution myself (sorry for the trouble).

    It appears that assigning a color to a material during runtime also sets this color in the original asset instance (in editor). So if I want several different colored materials it seems I must predefine them in the editor and cannot color them dynamically during runtime from one base material. Appears a bit unlogical to me but however.

    I don't know how to change the thread title to [solved].
     
  3. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    You can instantiate materials to get a unique one for your needs.
    Something like:
    Code (csharp):
    1.  
    2. Dictionary<Material<Dictionary<Color32, Material>> storedMaterials;  
    3.  
    4. Material GetUniqueMaterialFromMaterialAndColor(Color32 color, Material sourceMaterial)
    5. {
    6.     if (storedMaterials == null) storedMaterials = new Dictionary<Material<Dictionary<Color32, Material>>();
    7.  
    8.     if (!storedMaterials.ContainsKey(sourceMaterial))
    9.     {
    10.         Dictionary<Color32, Material> newDict = new Dictionary<Color32, Material>();
    11.         storedMaterials.Add(sourceMaterial, newDict);
    12.     }
    13.  
    14.     if (!storedMaterials[sourceMaterial].ContainsKey(color)) {
    15.         Material clone = Material.Instantiate(sourceMaterial) as Material;
    16.         clone.color = color;
    17.         storedMaterials[sourceMaterial].Add(color, clone);
    18.     }
    19.     return[sourceMaterial][color];
    20. }
     
    Last edited: May 25, 2015
    krougeau likes this.
  4. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Thanks ThermalFusion this is an interesting addition. Currently I have solved this with several instances in Editor but when also shaders and textures will be switched this method will become handy.