Dynamic Mesh Combining in Unity with C#

Combine meshes with different colors

This part of the tutorial is independent of the rest of the tutorial, so you can safely ignore it if you want to. The reason that I included it is that in Unity's example on how to combine meshes (found here) it is assumed that all meshes have the same color. But what are you supposed to do if they have different colors? So in this part of the tutorial you will learn how to combine meshes with different colors into one mesh.

First of all we need more trees, so copy the tree you created in the last part three times. Then press play, click on the "Stats" button while in Game view, and notice the amount of "Batches." In my case we have 22 batches, and this is the number we want to decrease by using mesh combining.

First of all we need a game object that will hold the combined mesh, so create a new game object and name it "Tree combined multicolor." To that game object you have to add a Mesh Renderer and a Mesh Filter. In the Mesh Renderer, set the material size to "2" and first add the "Leaf" material and then the "Wood" material you created in the previous part.

Create a new script called "TutorialCombineAll" and add it to the "_Controller" game object. Add the following to the script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//Combine trees with different materials into one mesh
public class TutorialCombineAll : MonoBehaviour
{
    //Array with trees we are going to combine
    public GameObject[] treesArray;
    //The object that is going to hold the combined mesh
    public GameObject combinedObj;

    void Start() 
    {
        CombineTrees();
    }

    //Similar to Unity's reference, but with different materials
    //http://docs.unity3d.com/ScriptReference/Mesh.CombineMeshes.html
    void CombineTrees() 
    {
        //Lists that holds mesh data that belongs to each submesh
        List<CombineInstance> woodList = new List<CombineInstance>();
        List<CombineInstance> leafList = new List<CombineInstance>();
        
        //Loop through the array with trees
        for (int i = 0; i < treesArray.Length; i++)
        {
            GameObject currentTree = treesArray[i];

            //Deactivate the tree 
            currentTree.SetActive(false);

            //Get all meshfilters from this tree, true to also find deactivated children
            MeshFilter[] meshFilters = currentTree.GetComponentsInChildren<MeshFilter>(true);

            //Loop through all children
            for (int j = 0; j < meshFilters.Length; j++)
            {
                MeshFilter meshFilter = meshFilters[j];

                CombineInstance combine = new CombineInstance();

                //Is it wood or leaf?
                MeshRenderer meshRender = meshFilter.GetComponent<MeshRenderer>();

                //Modify the material name, because Unity adds (Instance) to the end of the name
                string materialName = meshRender.material.name.Replace(" (Instance)", "");

                if (materialName == "Leaf")
                {
                    combine.mesh = meshFilter.mesh;
                    combine.transform = meshFilter.transform.localToWorldMatrix;

                    //Add it to the list of leaf mesh data
                    leafList.Add(combine);
                }
                else if (materialName == "Wood")
                {
                    combine.mesh = meshFilter.mesh;
                    combine.transform = meshFilter.transform.localToWorldMatrix;

                    //Add it to the list of wood mesh data
                    woodList.Add(combine);
                }
            }
        }


        //First we need to combine the wood into one mesh and then the leaf into one mesh
        Mesh combinedWoodMesh = new Mesh();
        combinedWoodMesh.CombineMeshes(woodList.ToArray());

        Mesh combinedLeafMesh = new Mesh();
        combinedLeafMesh.CombineMeshes(leafList.ToArray());

        //Create the array that will form the combined mesh
        CombineInstance[] totalMesh = new CombineInstance[2];

        //Add the submeshes in the same order as the material is set in the combined mesh
        totalMesh[0].mesh = combinedLeafMesh;
        totalMesh[0].transform = combinedObj.transform.localToWorldMatrix;
        totalMesh[1].mesh = combinedWoodMesh;
        totalMesh[1].transform = combinedObj.transform.localToWorldMatrix;

        //Create the final combined mesh
        Mesh combinedAllMesh = new Mesh();

        //Make sure it's set to false to get 2 separate meshes
        combinedAllMesh.CombineMeshes(totalMesh, false);
        combinedObj.GetComponent<MeshFilter>().mesh = combinedAllMesh;
    }
}

What's different in the script above compared with Unity's example is that we first combine all Wood into one mesh and all Leaf into another mesh. When we have these two different meshes, we can combine them into one mesh. It is important that you add them in the same order as you added the materials in the Mesh Renderer. And that's the secret behind combining meshes with different colors into one mesh.

Add the trees and the game object "Tree combined multicolor" to the script. If you now press play you should see the following:

Trees with different colors combined into one mesh in Unity

...and if you click the Stats button you should see that the number of batches have decreased from 22 to 18. It might not sound like much, but when we have thousands of trees, like we will have in the next part of the tutorial, you will notice a dramatic difference. So head to the next part of the tutorial!