[Solved] Suggestions for reducing Draw Calls on this Control Panel object?

Currently working on a mobile (Gear VR) app. I’m looking for suggestions as to how I might reduce the total Draw Calls in this control panel object. Comes to 15 draw calls which doubles to 30 in VR mode.

Currently the green ‘console’ object is one mesh and each rectangular button is a (quad) mesh with its own material and Collider. Colliders are used for raycasting - the player looks at each button with head tracking to select it. Each button needs to be able to change appearance and/or color independent of the others.

Correct me if I’m wrong, but I don’t think a Texture Atlas would help in this scenario since I need to be able to change each button image at will.

Any ideas on how to make this more efficient?

I would try using new UI in worldspace…

But texture atlas would help also, you just need to have the UV’s setup so that each quad displays correct image from atlas.

Or test some of those optimizer plugins,

*Warning, make backup first as they might change many things in the project…

1 Like

Thanks for the suggestions mgear.

Maybe I don’t quite understand how texture atlas works. I could set up each quad with the proper UV to display the proper section of the Atlas, but how could I then switch images on each quad when needed? A new mesh object with different UV mapping?

I think I will give the new Unity UI a try. Don’t know why I didn’t try that first, actually. I guess I decided no to use it because I was using the raycast setup for selecting each button, but I could still use it to display the images.

I would bake UV data into vertex colors, and offset each button UV (vertex colors in this case) via script, to match the desired icon on a texture atlas. It should give 1 draw call in total I think.

When using the the Unity UI, a sprite with the ‘Button Script’ component can easily swap out to another sprite upon rollover, press, etc… http://unity3d.com/learn/tutorials/modules/beginner/ui/ui-button

If all your sprites are on the same atlas, that’s the one draw call.

If you bring your sprites in one at a time as separate images, make sure you set the packing tags such that they are all on the same atlas.

Don’t use the built in Unity sprites… Packing tags are f’kt-up.

Highly recommend the excellent Texture Packer and free Texture Packer Importer available on the Asset Store

1 Like

It does not.

Any UV offset in code, or manipulation of render materials via scripting increases the draw calls. You do, however, get Vertex colours for free, provided that you use a fixed function shader what will display vertex colors

Thanks for the texture packing tips, this is something I haven’t tried before. I guess I can’t use the Unity Sprite Packer because I am in an Android project and don’t have the Android pro license. I’ll give that Texture Packer app a look-see.

Yeah, I agree, any material change will create another material instance in runtime. what I meant, is instead of changing the UV offset in code, it’s better to change the vertex colors values.
I’ve already done something similar in this project, the whole environment is built with 4 materials (1 master material 90% of the meshes(with Lut textures, and uvs baked into vertex colors), 1 for decals, 1 for glass, and 1 for small props) and everything seems to batch properly.

Indeed! :slight_smile:
Here’s some code to do just that:
[Attach to your quads]

private Mesh _mesh;
private Vector3[] _verts;
private Color32[] _colors;
private int _vertsLength;

private Color32 _onColor = new Color32(255, 195, 0, 255);
private Color32 _offColor = new Color32(25, 32, 40, 255); // Whatever colors you want

  void Awake()
      {
         _mesh = GetComponent<MeshFilter>().mesh;
         _verts = _mesh.vertices;
         _vertsLength = _verts.Length;
         _colors = new Color32[_vertsLength];
      }
    
    
void Start()
      {
         ChangeColor(_offColor);
      }
    

     public    void ChangeColor(Color32 color)
      {
         for (int i = 0; i < _vertsLength; i++)
         {
            _colors[i] = color;
            _mesh.colors32 = _colors;
         }
      }

Won’t work with all shaders. Here’s a simple one:

Shader "VertexColor" {
    Properties {
       _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
       Pass {
           Lighting On
           ColorMaterial AmbientAndDiffuse
           SetTexture [_MainTex] {
              combine texture * primary DOUBLE
           }
       }
    }
}

Still… Highly recommended to switch out to the Unity UI… Will handle sprite swaps and vert colors

1 Like

yeah, I like the sound of the UV offset and whatnot, but it is a little over my head. :slight_smile:

And - I already switched the images to use the Unity UI along with a sprite sheet. The 14 draw calls from the images are now 1 draw call! So I’m really saving 26 draw calls in VR mode since everything is doubled. :slight_smile:

Thanks so much for your help and suggestions everyone. I learned a lot this evening and my project is much more efficient. Also, that Texture Packer app is very quick and easy to use.

2 Likes