I am building this scene in 3D using Unity 2019.3.13's Universal Render Pipeline. I have a block prefab that I want to instance, but I want to choose which are yellow and which are blue (you can see the materials are basically the same). How can I write a shader that will allow me to pick either yellow or blue in the editor for each one? Is this possible? What is the most optimal way to make dozens of identical blocks where the color is different for specific instances?

enter image description here

(I would prefer a script to a graph, something with a simple switch/boolean input and hex values: yellow: e4c658 blue: 32676a

  • \$\begingroup\$ Presumably you considered using MaterialPropertyBlocks for this? \$\endgroup\$
    – DMGregory
    May 15, 2020 at 0:04

1 Answer 1


If you just want chequerboard alternation, we can do this with a single material, and save you making/positioning/rendering individual cubes.

Chequerboard alternating material

You can see from the selection wireframe in this screenshot, we're drawing far fewer triangles this way than if every cube was a separate mesh with a distinct material from its neighbours. That also means less overdraw from interior faces that we never see.

Here I assume that each of your cubes is 1 unit wide, and they're placed at integer coordinates in world space. We can scale/shift the effect if you need a different grid alignment though.

Shader "Custom/Chequer Volume"
        _Color ("Color", Color) = (0.8941,0.7764,0.3450,1)
        _OtherColor("Other Color", Color) = (0.1960,0.4039,0.4156,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.7
        _Metallic ("Metallic", Range(0,1)) = 0.0
        Tags { "RenderType"="Opaque" }
        LOD 200

        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
            float2 uv_MainTex;
            float3 worldPos;
            float3 worldNormal;

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        fixed4 _OtherColor;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
            // put more per-instance properties here

        void surf (Input IN, inout SurfaceOutputStandard o)
            float3 inside = round(IN.worldPos - 0.1f * IN.worldNormal);
            float parity = abs(fmod(inside.x + inside.y + inside.z, 2.0f));

            fixed4 color = lerp(_Color, _OtherColor, parity);

            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
    FallBack "Diffuse"
  • \$\begingroup\$ Hey, Gregory, how are you? This is awesome, but my blocks have bevels and the topology is slightly more complicated than I led on. I simplified the problem for brevity. I decided to create "prefab variants" where the only difference is the material. I don't like having two materials where the only difference is color though... ... yes, I will see if this looks good. I will use Blender to bake Normal and AO maps from a hi-res version. \$\endgroup\$ May 17, 2020 at 8:00
  • 1
    \$\begingroup\$ I've also tested this with a bevelled cube and it worked in that case too. That said, two separate materials is likely to also be fairly efficient, since all the blues can be drawn together in one batch, followed by all the yellows in a second batch. \$\endgroup\$
    – DMGregory
    May 17, 2020 at 8:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .