Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved CombineMesh not working as expected

Discussion in 'Scripting' started by PaperMouseGames, Dec 3, 2021.

  1. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Hi there, I'm trying to combine meshes for grass in my game and I've been following the documentation but it doesn't seem to be working for me and I'm not sure what's wrong.

    I'm following the code in the example on this page: https://docs.unity3d.com/ScriptReference/Mesh.CombineMeshes.html

    My code is identical to that page except I added a few Debug.Logs to see what's happening.

    All my grass uses the same material and I have that same material on the parent object's MeshRenderer as well (the object that holds the MeshCombine script).

    So the script is running, and it is deactivating all my grass objects as well as adding them to the meshFilters array.

    Problem is, even though the parent object is active, and I can see that it has created a new mesh in its mesh filter, I can't see anything. All the grass is just gone.

    Any idea what's going on? I'm guessing I'm missing some setting or something.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,278
    For some period of time there was broken CombineMesh code circulating. Perhaps you got some of that?

    Whatever the problems were (I forget but there were two or three issues that people kept seeing), I have a fully-operational mesh combination example in my MakeGeo project. Just search for "combine"

    MakeGeo is presently hosted at these locations:

    https://bitbucket.org/kurtdekker/makegeo

    https://github.com/kurtdekker/makegeo

    https://gitlab.com/kurtdekker/makegeo

    https://sourceforge.net/p/makegeo
     
  3. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    @Kurt-Dekker

    Thanks for the reply. So I found the ExampleCombinerImproved script which I'm fairly sure is the one in question. It's working well for standard meshes, but not for my grass. Here is a gif of what's going on when I hit play:

    Mesh Combine 01.gif


    So the cube is the parent with the script, the spheres and the grass are children with mesh filters. The spheres use a standard material, and the grass uses a material with my grass sprite sheet and a custom shader. I tried this on a new project as well, without my custom shader, but the same grass mesh I'm using, and it does this where it sort of merges with the spheres.

    Not sure why this would be happening to the grass mesh. Any ideas?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,278
    Well what's moving the grass vertices? It seems like maybe that logic is grabbing the source vertex positions off the brown orbs, animating it and applying it to the grass verts!
     
  5. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    The custom shader is moving the vertices, but when I tried it with a regular material on the same grass mesh, I had the same result (except it wasn't moving) but it ended up inside one of the spheres.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,278
    Certainly smells like the combine has a bug. No idea why it only manifests on the grass but perhaps it is related to submesh number or who knows. Did you try it with the combiner in MakeGeo? I bet it will work... don't know about the shader displacement stuff though.

    EDIT: I see you did try it with the script, never mind.

    EDIT2: why does the cube AND the nearest brown ball go away. That seems also suspect. Are you sure you are ONLY running the code from MakeGeo?
     
  7. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    So Here is the result in a brand new project:

    Mesh Combine 02.gif

    Same deal as before, cube is parent, grass mesh is the green mesh, and the other 6 are Unity 3D objects (spheres, cylinder, and quad). Both materials used are standard and use the standard shading, one is transparent, the other opaque. No custom shaders at all.

    The grass mesh seems to be putting it's material on one of the other meshes and disappearing, or maybe taking the shape and position of the other mesh? Not sure.

    Here is the code, it's just copy paste from the linked project unless I messed something up but I think it's all the same.

    Code (CSharp):
    1. public class MeshCombiner : MonoBehaviour
    2. {
    3.     private void Start()
    4.     {
    5.         MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
    6.         List<CombineInstance> combines = new List<CombineInstance>();
    7.  
    8.         // KurtFixed: handle materials... I mean, they're kind of important!
    9.         List<Material> materials = new List<Material>();
    10.  
    11.         for (int i = 0; i < meshFilters.Length; i++)
    12.         {
    13.             // KurtFixed: we gotta ignore ourselves or our count would be off!
    14.             if (meshFilters[i] == GetComponent<MeshFilter>())
    15.             {
    16.                 continue;
    17.             }
    18.  
    19.             // KurtFixed: tally up the materials, since each mesh could have multiple
    20.             var mr = meshFilters[i].GetComponent<MeshRenderer>();
    21.             for (int j = 0; j < mr.materials.Length; j++)
    22.             {
    23.                 var combine = new CombineInstance();
    24.  
    25.                 combine.mesh = meshFilters[i].sharedMesh;
    26.                 combine.subMeshIndex = j;
    27.  
    28.                 combine.transform = meshFilters[i].transform.localToWorldMatrix;
    29.                 meshFilters[i].gameObject.SetActive(false);
    30.  
    31.                 combines.Add(combine);
    32.  
    33.                 materials.Add(mr.materials[j]);
    34.             }
    35.         }
    36.         transform.GetComponent<MeshFilter>().mesh = new Mesh();
    37.         transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combines.ToArray(), false);
    38.         transform.gameObject.SetActive(true);
    39.  
    40.         // KurtFixed: inject the original materials
    41.         gameObject.GetComponent<MeshRenderer>().materials = materials.ToArray();
    42.     }
    43. }
    Finally, here is the cube parent's inspector, pretty sure it's all good here too

    upload_2021-12-3_14-57-22.png

    Not sure what's going on, an issue with my grass mesh maybe, but I can't imagine why.
     
  8. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Ok so I think I fixed it. Turns out it had nothing to do with my shader and it was a really easy fix.

    The grass mesh I was using to test this and that I was trying to combine was an imported mesh and I needed to have "Read/Write Enabled" turned on in the mesh settings.

    After turning that on it's working exactly as expected :)
     
    bajja and Kurt-Dekker like this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,278
    AHA! That's awesome! Thanks for the followup... was it printing a warning / error in the console?
     
  10. PaperMouseGames

    PaperMouseGames

    Joined:
    Jul 31, 2018
    Posts:
    434
    Nope, nothing. Just that weird behavior shown in the gif. I only figured it out after finding this post:

    https://answers.unity.com/questions/1679964/combining-meshes-from-imported-models.html

    So the key was that I was using an imported mesh and I hadn't thought to search for that specifically until today.
     
  11. aacstudio

    aacstudio

    Joined:
    Dec 14, 2019
    Posts:
    1
    Man you are a genius!! This saved my day!
    Thank you ma man!
     
    PaperMouseGames likes this.
  12. XJonOneX

    XJonOneX

    Joined:
    Dec 19, 2017
    Posts:
    99
    Unity now throws a warning when trying to combine meshes without read/write on.