Search Unity

Combine meshes efficiently

Discussion in 'World Building' started by Grafer, Feb 9, 2019.

  1. Grafer

    Grafer

    Joined:
    May 30, 2015
    Posts:
    19
    Hi!
    I am creating a world based on blocks just like in Minecraft etc.
    I have a block class and a chunk class.
    Each block has up to 6 meshes, one for each side.

    Code (CSharp):
    1. Mesh mesh = new Mesh();
    2.         mesh = GenerateBlockSide(mesh, side);
    3.         GameObject blockSide = new GameObject("block side");
    4.         blockSide.transform.position = blockPosition;
    5.         MeshFilter meshFilter = blockSide.AddComponent(typeof(MeshFilter)) as MeshFilter;
    6.         meshFilter.mesh = mesh;
    7.         chunkParent.meshFiltersList.Add(meshFilter);
    8.         GameObject.Destroy(blockSide);
    In my Chunk class, I create 16x16x16 blocks (4096) and store all generated blocks meshfilters list to combine them together for a performance boost.

    Code (CSharp):
    1. MeshFilter[] meshFilters = meshFiltersList.ToArray();
    2.         CombineInstance[] combineSides = new CombineInstance[meshFilters.Length];
    3.         int index = 0;
    4.         foreach (MeshFilter meshFilter in meshFilters)
    5.         {
    6.             combineSides[index].mesh = meshFilter.sharedMesh;
    7.             combineSides[index].transform = meshFilter.transform.localToWorldMatrix;
    8.             index++;
    9.         }
    10.         MeshFilter blockMeshFilter = chunkObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
    11.         blockMeshFilter.mesh = new Mesh();
    12.         blockMeshFilter.mesh.CombineMeshes(combineSides);
    13.         MeshRenderer blockMeshRenderer = chunkObject.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    14.         blockMeshRenderer.material = blockMaterial;
    15.         meshFiltersList.Clear();
    The problem is I am creating and destroying thousands of gameobjects each frame and adding a component to it. Is there any other way to combine all of these meshes without the need to create gameobject each time? Can I store somehow all of the vertices, normals, UV, and triangles of each block side in some one common list for each parameter and then based on it create a new mesh?
    I'd be really grateful for any help.
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
  3. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    You don't say what a block is. But assuming blocks have the same structure, you simply create a new mesh. You have the data that represents the verts/tris/uv/normals. That's just a single instance because it's the same for all blocks. Per block you store rotation/position. Creating a mesh is a flow of for each block take your block data and transform it, then write it out to the new mesh.

    That's the very basic idea there is much much more bigger picture. Like partitioning that by material. Having a system where you only create the chunk mesh when chunks come in/out of range.

    But for example I have a fully fleshed out minecraft style system that uses faces, only creates faces that are visible. The smallest component is a simple plane. It's around 1000 lines of code, uses native collections, does not use DrawMesh or instanced rendering. Performs very well.

    The thing is even if you fix how you create meshes, unless you go to a system which only creates faces that are visible, it's going to have horrible render performance at any scale (creation cost aside). So think about what your use case is or you will end up doing a bunch of work for nothing.