Mesh CombineMeshes results EMPTY mesh if called from Coroutine or Start

  • If I call the CombineMesh function from Start() or Coroutine, the result mesh always has vertex count == 0.
  • The input meshes are validated correctly. I can even create Entities (Unity ECS) to render the mesh instead of MeshFilter, correctly. I had debug the code line by line, each input mesh has a lot of vertices but the result is always 0.
  • If I call from the context menu, it works normally (successfully), even when pausing the player and call the function from frame 1.
   //
    public void Start()
    {
        // doesn't work
        this.TestCombineMesh();
    }

    // works if called from context menu
    [ContextMenu("Test combine mesh")]
    public void TestCombineMesh()
    {
        // assume getting a game object with a lot of mesh filter children
        GameObject source = new GameObject();
        this.CombineMesh(source);
    }

//
    // assume the input game object has a lot of mesh filter children
    public void CombineMesh(GameObject theObj)
    {
        theObj.transform.position = Vector3.zero;
        MeshFilter[] filters = theObj.GetComponentsInChildren<MeshFilter>();
        CombineInstance[] combine = new CombineInstance[filters.Length];
        for (int i = 0; i < filters.Length; ++i)
        {
            combine[i].mesh = filters[i].sharedMesh;
            combine[i].transform = filters[i].transform.localToWorldMatrix;
        }
        Mesh newMesh = new Mesh();
        newMesh.CombineMeshes(combine);
        Debug.Log("vertex count " + newMesh.vertexCount);

        GameObject goNew = new GameObject("combined_" + theObj.name);
        goNew.transform.position = Vector3.zero;
        goNew.AddComponent<MeshFilter>().sharedMesh = newMesh;
        goNew.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
    }

Is this a bug? Any reason for the CombineMesh result empty mesh? Anyway to workaround this?

Thank you very much!

p/s: It results empty mesh if being called from Update() or OnGUI() too

How exactly do you tell if the mesh is empty? Did you check in the inspector of the created object? Have you actually tried putting a Debug.Log inside your combine loop to see how many objects it iterates over? Generally what exact debugging steps have you done yet on your own and what are the results? Currently you just present us with a code snippet which will result in an empty mesh since your “source” is an empty object and all we have is your comment that it actually comes from somewhere else and that your result is an empty mesh.

It would be great to have more details here. Are you sure that those child objects actually have a MeshFilter? Maybe the meshes may have a SkinnedMeshRenderer which doesn’t have a MeshFilter? We don’t know, that’s something you have to test in your project.

  • I attached debugger to the Editor, and checked line by line.

  • The input is a lot of meshes. Like I said, I’d validated them, they each displayed correctly before being combined.

image

  • But after combined, the result mesh is empty.

image
image

  • I just found out that there are logs in the console, it said Cannot combine mesh that does not allow access: the_mesh_name. But when I called the combine function from the ContextMenu, it doesn’t log so and combined successfully. Does invoking from ContextMenu skipped the mesh read/write enabled?

  • The meshes are imported as mesh_name.asset which are pure Unity meshes, not .fbx or .obj. Unity offer no option to mark the mesh read/write enabled.

image