What does mesh.optimize do?

Hi all,

I have a program where I need to create a mesh every frame using combine meshes and if I don’t call mesh.optimize after combining the mesh, the object will not display in the world. Why is it necessary to call mesh.optimize? Doing mesh.recalculateBounds/Normals does not fix the problem. Mesh.optimize is very expensive so I’d like to do as little a possible and still have my object appear after combining.

My guess is you aren’t “registering” the changes, and Optimize happens to be doing that for you as a side-effect. For example, mesh.vertices[0]=p1; doesn’t actually do anything. The assignment to mesh.vertices = newArray; seems to trigger writing the new mesh to the GPU (the code samples do this, but don’t explicitly say it.)

Optimize mentions tri-strips. If your model has 50 tris in it, you need a list of 150 verts to describe them. But, most models can be divided into long rows of adjacent triangles which share sides. Each new triangle is the last side of the previous one, plus one new vert. You can now describe 50 triangles using only 52 points. Graphics cards love to burn through these “tri-strip” lists – they only have to lookup one new vert for most triangles.

But, as the docs say, it’s only an efficiency issue: time wasted doing it vs. time saved later.

I always create a new Mesh when using CombineMeshes(), and it works fine without the need to 'register' anything with some vertex array setter side-effect.

e.g:

var joinedMesh = new Mesh();
meshFilter.sharedMesh = joinedMesh;
joinedMesh.CombineMeshes(meshesToJoin.ToArray());

where:

  • meshFilter is the MeshFilter component to add the combined mesh to.
  • meshesToJoin is an IEnumerable(CombineInstance) (i.e. the list of mesh/transform pairs your joining)

EDIT: Just re-read the question and saw the 'every frame' part. Not sure if creating a new mesh every time would be appropriate in this case.

EDIT 2: Including a more comprehensive sample to give more context to how the above can be used:


public class JoinAndMove : MonoBehaviour
{
    public GameObject[] ObjectsToJoin;

    void Start()
    {
        var meshesToJoin = ObjectsToJoin.Select( obj =>
        {
            var filter = obj.GetComponent<MeshFilter>();
            var combineInstance = new CombineInstance();
            combineInstance.mesh = filter.mesh;
            combineInstance.transform = obj.transform.localToWorldMatrix;
            return combineInstance;
        });

        var meshFilter = gameObject.GetComponent<MeshFilter>();
        var joinedMesh = new Mesh();
        meshFilter.sharedMesh = joinedMesh;
        joinedMesh.CombineMeshes(meshesToJoin.ToArray());

        // Note the below move is done to simply prevent the new joined 
        // mesh from overlapping the original meshes that were joined.
        transform.position = new Vector3(
          transform.position.x, transform.position.y + 2, transform.position.z);
    }
}