- Home /
Combine meshes without moving them?
When I used the combine meshes script (https://docs.unity3d.com/ScriptReference/Mesh.CombineMeshes.html) it moves the meshes. I've read to try moving to parent to 0,0,0 1st or multiply each child mesh localToWorldMatrix with the parent's worldToLocalMatrix, but neither of those fix the issue. I've pasted the code below as an example. Does anyone know how to combine a bunch of child meshes without them being moved?
Vector3 tempPos = gameObject.transform.position;
gameObject.transform.position = Vector3.zero;
gameObject.AddComponent<MeshFilter>();
gameObject.AddComponent<MeshRenderer>();
MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];
Material mat = null;
Matrix4x4 pMat = gameObject.transform.worldToLocalMatrix;
for (int i = 0; i < meshFilters.Length; i++)
{
mat = meshFilters[i].GetComponent<MeshRenderer>().material;
combine[i].mesh = meshFilters[i].sharedMesh;
combine[i].transform = pMat * meshFilters[i].transform.localToWorldMatrix;
meshFilters[i].gameObject.SetActive(false);
}
transform.GetComponent<MeshFilter>().mesh = new Mesh();
transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
gameObject.GetComponent<MeshRenderer>().material = mat;
transform.gameObject.SetActive(true);
gameObject.transform.position = tempPos;
Answer by homer_3 · Feb 17, 2021 at 03:07 AM
I think I figured out the issue. I think there's a vertex limit or something for each mesh. If I reduce the number of meshes I'm combing at a time, it works fine. So I needed to change my setup so each parent gameobject that wants to combine all its meshes only has so many meshes to prevent going over the limit.
A Mesh by default has an 16 bit index buffer and therefore can handle about 64k vertices. However you can change the index format of your target mesh so it uses a 32 bit index buffer. Of course a 32 bit index buffer requires twice the memory on the GPU for the same amount of triangles, however you can now address 4 billion (milliard) vertices in one mesh.
In the past Unity did only support 16 bit index buffers, though the index format setting was added several years ago. So this should fix your problem:
// [ ... ]
Mesh mesh = new Mesh();
mesh.indexFormat = IndexFormat.UInt32;
mesh.CombineMeshes(combine);
GetComponent<MeshFilter>().sharedMesh = mesh;
GetComponent<MeshRenderer>().sharedMaterial = mat;
Note that you should always use the sharedMesh / sharedMaterial property if possible. Otherwise you loose any kind of batching between objects with the same material. Whenever you use the mesh / material property Unity will create a duplicate of the assigned mesh / material for this instance only.