Is it possible to have a prefab of a cube, which has instances with different colours?

Hi, I’m trying to keep the number of draw calls down. I have a lot of cubes, which have all of the same textures, scripts, etc., the only thing that will be different is the colour (I’ll have like 5 or 6 colours).

I have been reading a lot about max draw calls for mobile devices. From what I gather I believe that when a texture is applied to a game object prefab, all instances of the prefab on the screen will only use one draw call (per light?) for that texture, but when that texture is on a different material (because of the colour in my case), another draw call is required…

I’m new at this, so I may be wrong with what I said above, but if I’m right, is there a way to still only use the 1 draw call for that texture for every cube regardless of the colour change?

Please correct me if I was wrong with what I said about draw calls, I’m trying to wrap my head around this stuff, thanks for you help!!

You are roughly right, but it’s materials rather than textures that count.

Setting the instance of a prefabs material to a different colour will break batching. Your choice is to have a custom shader that uses the vertex colours of the model to tint it - this does not break batching.

Every vertex of a model has the opportunity to have a colour associated with it, you set it using the colors on the mesh. If for instance you used this shader:

Shader "whydoidoit/Vertex Color Tinted" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float2 uv_MainTex;
          float4 color;
      };
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * IN.color;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

The you could colour each cube separately and still batch by setting those vertex colours (probably all to the same value). The array is the same size as the vertices array:

    var mf = GetComponent<MeshFilter>();
    var colors = new Color[ mf.sharedMesh.vertexCount];
    for(var i = 0; i < colors.Length; i++)
         colors *= new Color(1,0,0,1);  //Your color here*

mf.mesh.colors = colors;

You are correct. If the material is the same on several objects in the scene, they are batched to produce 1 draw call. And mobile devices are sensitive to draw calls, if you want to support many of the cheaper devices. However, the number of texture swaps is very low, so that is a good thing.

I haven’t tried this, but I think it would work. If you’re going for something like random colors, the shader could instantiate a global index that is incremented for each pass, and that index could access a pre-built random array of colors and apply them to the vertices directly in the pipeline, which would allow you to use the same material for all cubes but have random colors on them. If you kept everything ordered, the app could also track the color of each cube independently, if they aren’t created quickly one after the other.

If you created a mesh with 6 cubes where each vertex is a different color, you still run into the problem of writing to variables in the shader to do something like say rotate or move each cube individually. In that case, you may incur more cost than the draw calls. I would say do some tests on some low end and high end devices to get an idea of what your limits are with the 6 draw calls. My personal experience with Android devices is that you can stay pretty decent with 15’ish draw calls and still be viable for older devices. It’s the transparent textures and fill rates on the older devices that really start to get you.