How to correctly collapse all submeshes into one?

I’m trying to remove submeshes from a mesh, as they are in fact all going to be rendered with one material. I thought this code should do it:

            var oneTrueSubmesh = mesh.GetSubMesh(0);
            oneTrueSubmesh.firstVertex = oneTrueSubmesh.baseVertex = 0;
            oneTrueSubmesh.vertexCount = mesh.vertexCount;
            oneTrueSubmesh.indexStart = 0;
            oneTrueSubmesh.indexCount = mesh.triangles.Length;
            mesh.SetSubMesh(0, oneTrueSubmesh);
            mesh.subMeshCount = 1;

But this sometimes produces an error:

I’ve also tried setting the subMeshCount to 1 before calling SetSubMesh, despite the scary warning in the docs that this will truncate the index list. But it produces the same result.

What’s the correct way to just remove/combine all the submeshes of a mesh, leaving me with an ordinary mesh that’s not subdivided?

Thanks,

  • Joe

I might be wrong, but I think that the reason you get that error, is because the meshes might probably have all been baked together. If they weren’t baked, but just grouped, or combined, or parented to each other, I think the code would have worked easily.

I’m afraid I have no idea what you’re talking about. It’s a single mesh, with several submeshes. I’m just trying to combine those into a single submesh (or if you prefer, a mesh that doesn’t use submeshes).

I don’t wish to necro an older thread, but I felt it worthwhile posting as I have a solution that worked for me, and an explanation that others & OP may find useful, and is still relevant in current versions of Unity. We are using this a batching system to reduce draw calls in 2020.3 LTS.

OP was assigning the number of triangles to the indicesCount property:

oneTrueSubmesh.indexCount = mesh.triangles.Length;

The issue here is that the number of triangles for the entire mesh is not the same as the number of triangle indices when you have submeshes. You can end up where you have more indices than number of triangles with submeshes.

To get around this, we count the actual number of triangle indices before we adjust the submeshes. This means that your indices for your triangles are consistent with your new, single submesh with that of your older, multiple submeshes.

List<int> triIndices = new List<int>();
for (int i = 0; i < mesh.subMeshCount; i++)
{
    int[] indices = mesh.GetIndices(i);
    triIndices.AddRange(indices);
}
var oneTrueSubmesh = mesh.GetSubMesh(0);
oneTrueSubmesh.firstVertex = oneTrueSubmesh.baseVertex = 0;
oneTrueSubmesh.vertexCount = mesh.vertexCount;
oneTrueSubmesh.indexStart = 0;
oneTrueSubmesh.indexCount = triIndices.Count;        
mesh.SetSubMesh(0, oneTrueSubmesh);
mesh.subMeshCount = 1;

You will want to wrap your code in a submesh count check, as trying to do this on objects with one submesh has led to some odd results at times (errors, mainly).
i.e.

if(mesh.subMeshCount > 1){
    // do the mesh combining
}