Search Unity

Bug (Solved- mesh import issue) Not getting a mesh from mesh.CombineMeshes()

Discussion in 'Scripting' started by ErinZ, Jul 24, 2021.

  1. ErinZ

    ErinZ

    Joined:
    Aug 13, 2019
    Posts:
    4
    THE SOLUTION
    Hello random google search from the future. This thread is being buried now. If you are like me you have spent too much stress wondering why your perfectly good code just sin't working but also maddeningly isnt giving any error messages. it just compiles. Only problem is your Combine Mesh outputs a completely empty mesh. Well the solution is quite simple. all you have to do is go into unity and
    navigate to your model you are trying to combine. Click Read/Write Enabled
    this will allow the script your write to actually read the mesh you import and get the model data from it. Yes. I know it was that simple. Couldn't unity throw a little debug message if you try to combine a mesh it can't read? yeah but that would be too easy im sure. or maybe its thrown somewhere else I don't know how to check. Who knows.



    old stuff \/\/\/\/\/
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    I have been working on this for hours trying to get combining meshes into my head. I finally got something working and everything runs supposedly. one small problem. there isn't a visual mesh at the end. I have tried poking at several different variables now and honestly I feel it should be working. If someone could please tell me why I am not getting a mesh from this?







    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ChunkManager : MonoBehaviour
    6. {
    7.     public static ChunkManager currentManager;
    8.  
    9.     //combined meshes per floor
    10.     public GameObject floor1;
    11.     public GameObject floor2;
    12.     public GameObject floor3;
    13.     public GameObject floor4;
    14.  
    15.     public bool combineFirstFloor = false;
    16.  
    17.     void Awake()
    18.     {
    19.         currentManager = this;
    20.     }
    21.  
    22.     private void LateUpdate()
    23.     {
    24.         if(combineFirstFloor)
    25.         {
    26.             CombinePerFloor(0);
    27.             combineFirstFloor = false;
    28.         }
    29.     }
    30.  
    31.     public void CombinePerFloor(int floor)
    32.     {
    33.  
    34.         //what have I done
    35.         //ok so this theoretically should be able to add a new list of combine instances every time we find a new material
    36.         List<List<CombineInstance>> combineInstanceListList = new List<List<CombineInstance>>();
    37.  
    38.         List<Material> materialList = new List<Material>();
    39.         CombineInstance combine = new CombineInstance();
    40.  
    41.         List<GameObject> currentFloor;
    42.  
    43.         //here we get a list of gameobjects with no children and singular meshfilters with no submeshes and only one material per mesh very simple
    44.         currentFloor = GridManager.currentManager.GetPiecesByFloor(floor);
    45.  
    46.         //go through every piece of the floor
    47.         for(int i = 0; i < currentFloor.Count; i++)
    48.         {
    49.             MeshFilter meshFilter = currentFloor[i].GetComponent<MeshFilter>();
    50.  
    51.             int check2 = CheckIfMaterialIsOnList(meshFilter.GetComponent<MeshRenderer>().material);
    52.  
    53.             //if the material already exists in the list
    54.             if (check2 != -1)
    55.             {
    56.                 combine.mesh = meshFilter.sharedMesh;
    57.                 combine.transform = meshFilter.transform.localToWorldMatrix;
    58.                 combineInstanceListList[check2].Add(combine);
    59.             }
    60.             //if the material doesnt exist in the list. update a bunch of lists
    61.             else
    62.             {
    63.                 List<CombineInstance> joey = new List<CombineInstance>();
    64.                 materialList.Add(meshFilter.GetComponent<MeshRenderer>().material);
    65.                 combineInstanceListList.Add(joey);
    66.  
    67.                 GameObject meshParent = new GameObject();                  
    68.                 MeshFilter mf = meshParent.AddComponent(typeof(MeshFilter)) as MeshFilter;
    69.                 MeshRenderer mr = meshParent.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    70.  
    71.                 mr.material = meshFilter.GetComponent<MeshRenderer>().material;
    72.                 meshParent.transform.SetParent(floor1.transform);
    73.  
    74.                 combine.mesh = meshFilter.sharedMesh;
    75.                 combine.transform = meshFilter.transform.localToWorldMatrix;
    76.  
    77.                 combineInstanceListList[combineInstanceListList.Count-1].Add(combine);
    78.             }
    79.             currentFloor[i].SetActive(false);
    80.         }
    81.  
    82.         //where the actual combinding of the meshes happens.
    83.         //a mesh for every material
    84.         for (int b = 0; b < materialList.Count; b++)
    85.         {
    86.             floor1.transform.GetChild(b).gameObject.GetComponent<MeshFilter>().mesh = new Mesh();
    87.             floor1.transform.GetChild(b).gameObject.GetComponent<MeshFilter>().mesh.CombineMeshes(combineInstanceListList[b].ToArray(),true,true);
    88.         }
    89.  
    90.  
    91.         //easy oeasy go through the whole material list and if the material matches ours then it will tell us its index.
    92.         //with that index we can then tell it where to insert the combineInstance since the combineInstance list and the materialList are in sync
    93.         int CheckIfMaterialIsOnList(Material m)
    94.         {
    95.             for(int i = 0; i < materialList.Count;i++)
    96.             {
    97.                 if(materialList[i] = m)
    98.                 {
    99.                     return i;
    100.                 }
    101.             }
    102.             return -1;
    103.         }
    104.     }
    105. }
     
    Last edited: Jul 26, 2021
  2. TheFunnySide

    TheFunnySide

    Joined:
    Nov 17, 2018
    Posts:
    200
    You are not doing yourself a favor by writing a function that works with a List of Lists.

    First write a Function that works with a single list then call this function in a loop to get your list of lists.


    Ultimately you need to Debug.Log what you are actully feeding into the
    CombineMeshes, i got this feeling its not getting any meshes.
     
    Last edited: Jul 24, 2021
  3. ErinZ

    ErinZ

    Joined:
    Aug 13, 2019
    Posts:
    4
    Yeah just rewrote a bit of the function to pass in a non stacked list and I get the same result.

    EDIT: added some debug logs to check the vertex count of the meshes being passed into the combine list and it all checks out over 20 vertices per mesh. They are just little floor tiles. So yeah still no visible mesh at the end. I told you the code seems to flow through and I am not sure why it isn't working.


    EDIT: I even threw a log there at the end to cycle through the combineInstances of the list right before I pass it into the mesh.CombineMeshes. all the meshes are there with their vertices. I am just not getting the output from CombineMeshes. It seems broken.

    EDIT: Just for funsies I tested a Debug.Log for the List with the ToArray() function. Still working fine and I can read all the combine instances and their vertices. CombineMeshes() is just not returning a visible mesh for some reason. Is it something to do with the transform matrix? I read somewhere about all the vertices being compressed to the same point but i thought I solved that with the combine.transform = meshFilter.transform.localToWorldMatrix;
     
    Last edited: Jul 24, 2021
  4. ErinZ

    ErinZ

    Joined:
    Aug 13, 2019
    Posts:
    4
    The top debug.Log returns 20 25 times. One time for each of the 25 tiles that each have 20 vertices in them.

    Then I put those meshes through a CombineMeshes() though I get 0 as my total vertex count

    Code (CSharp):
    1.             foreach(CombineInstance c in combineInstanceListList[b].ToArray())
    2.             {
    3.                 Debug.Log(c.mesh.vertexCount);
    4.             }
    5.             Mesh messss = new Mesh();
    6.             messss.CombineMeshes(combineInstanceListList[b].ToArray());
    7.  
    8.             Debug.Log(messss.vertexCount);

    EDIT: well I'm officially lost. I updated my code in my first post to be more to the point and remove the extra crap while documenting it. hopefully someone smarter than me can figure this out while I sleep here. It honestly feels like CombineMeshes() is broken. I am going to try another unity version though. Maybe it will fix my problem.

    EDIT: nope still having the problem on latest stable

    EDIT: triangulating the faces of my mesh didn't work either



    EDIT: OK this is NOT a programming issue. my code works perfectly. It is a mesh import issue. I have blender models imported via FBX. for some reason unity doesn't like this mesh when put through CombineMeshes. I put through a default cube and the code ran flawlessly. Guess I have to figure out my import settings
     
    Last edited: Jul 25, 2021