0

So, I am in the process of creating a infinite terrain system similar to Minecraft's. I am making it myself out of personal interest to learn. I have most everything working, and I have made some functions to generate the faces of cubes and then I'm adding it all together into a chunk, but for some reason I am getting a really weird thing where each row of the blocks are randomly much higher than the others, ruining the mesh entire. Anyone able to understand why, because I am completely lost as to the issue.

Note: The highlighted part is supposed to be a singular chunk, and it extends upwards over the entire chunk. Each set of them are a slight bit behind the previous, its supposed to be a completely flat face on the top.

enter image description here

// Face Generator
    public enum Face { top, bottom, north, south, west, east };
    public Mesh GetMeshDataFromFace(Face face, Vector3 pos)
    {
        Mesh _face = new Mesh();

        Vector3[] _normals = new Vector3[4];

        if (face == Face.top)
        {
            //Create the mesh for a upwards facing surface.

            _face.vertices = new Vector3[] {
                pos + new Vector3(0, 1, 0),
                pos + new Vector3(1, 1, 0),
                pos + new Vector3(1, 1, 1),
                pos + new Vector3(0, 1, 1)
            };

            _face.triangles = new int[]{
                0, 3, 2, 2, 1, 0
            };

            _normals = new Vector3[]{
                Vector3.up, Vector3.up,  Vector3.up, Vector3.up
            };
        }

        if (face == Face.bottom)
        {
            //Create the mesh for a upwards facing surface.

            _face.vertices = new Vector3[] {
                pos + new Vector3(0, 0, 0),
                pos + new Vector3(1, 0, 0),
                pos + new Vector3(1, 0, 1),
                pos + new Vector3(0, 0, 1)
            };

            _normals = new Vector3[]{
                Vector3.down, Vector3.down, Vector3.down, Vector3.down
            };

            _face.triangles = new int[]{
                0, 1, 2, 2, 3, 0
            };
        }

        if (face == Face.north)
        {
            //Create the mesh for a upwards facing surface.

            _face.vertices = new Vector3[] {
                pos + new Vector3(0, 0, 1),
                pos + new Vector3(1, 0, 1),
                pos + new Vector3(1, 1, 1),
                pos + new Vector3(0, 1, 1)
            };

            _normals = new Vector3[]{
                Vector3.right, Vector3.right, Vector3.right, Vector3.right
            };

            _face.triangles = new int[]{
                0, 1, 2, 2, 3, 0
            };
        }

        if (face == Face.south)
        {
            //Create the mesh for a upwards facing surface.

            _face.vertices = new Vector3[] {
                pos + new Vector3(0, 0, 0),
                pos + new Vector3(1, 0, 0),
                pos + new Vector3(1, 1, 0),
                pos + new Vector3(0, 1, 0)
            };

            _normals = new Vector3[]{
                Vector3.left, Vector3.left, Vector3.left, Vector3.left
            };

            _face.triangles = new int[]{
                0, 3, 1, 3, 2, 1
            };
        }

        if (face == Face.west)
        {
            //Create the mesh for a upwards facing surface.

            _face.vertices = new Vector3[] {
                pos + new Vector3(0, 0, 0), // 0
                pos + new Vector3(0, 1, 0), // 3
                pos + new Vector3(0, 1, 1), // 7
                pos + new Vector3(0, 0, 1) // 4
            };

            _normals = new Vector3[]{
                Vector3.back, Vector3.back, Vector3.back, Vector3.back
            };

            _face.triangles = new int[]{
                2, 1, 0, 0, 3, 2
            };
        }

        if (face == Face.east)
        {
            //Create the mesh for a upwards facing surface.

            _face.vertices = new Vector3[] {
                pos + new Vector3(1, 0, 0),
                pos + new Vector3(1, 1, 0),
                pos + new Vector3(1, 1, 1),
                pos + new Vector3(1, 0, 1)
            };

            _normals = new Vector3[]{
                Vector3.forward, Vector3.forward, Vector3.forward, Vector3.forward
            };

            _face.triangles = new int[]{
                0, 1, 2, 2, 3, 0
            };
        }

        _face.SetNormals(_normals);

        return _face;
    }

Chunks store block data as a singular byte[] array of 4096 indexs. Here is the code for generating the mesh

public Mesh CreateChunkMesh(ChunkObject chunkObj)
    {
        Chunk chunkData = chunkObj.chunkData;

        Mesh mesh = new Mesh();

        List<Mesh> meshesToCombine = new List<Mesh>();

        for (int i = 0; i < chunkData.blocks.Length; i++)
        {
            if (chunkData.blocks[i] != 0)
            {

                Vector3 blockPos = new Vector3((i % 16), Mathf.Floor(i % 256), Mathf.Floor((i % 256) / 16));
                Debug.Log(i + " | " + blockPos);

                if (i + 256 >= chunkData.blocks.Length)
                {
                    //This is the top layer of blocks.
                    if (!_loadedChunkObjs.ContainsKey(chunkObj.chunkPosition + new Vector3Int(0, 1, 0)))
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.top, blockPos));
                    }
                }

                if (i < 256)
                {
                    if (!_loadedChunkObjs.ContainsKey(chunkObj.chunkPosition + new Vector3Int(0, -1, 0)))
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.bottom, blockPos));
                    }
                }

                if ((i % 256) < 16)
                {
                    //This is the EAST layer of the chunk.
                    if (!_loadedChunkObjs.ContainsKey(chunkObj.chunkPosition + new Vector3Int(0, 0, 1)))
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.east, blockPos));
                    }
                }

                if ((i % 256) >= 240)
                {
                    //This is the WEST layer of the chunk.
                    if (!_loadedChunkObjs.ContainsKey(chunkObj.chunkPosition + new Vector3Int(0, 0, -1)))
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.west, blockPos));
                    }
                }

                if (i % 16 == 0)
                {
                    //This is the NORTH layer of the chunk
                    if (!_loadedChunkObjs.ContainsKey(chunkObj.chunkPosition + new Vector3Int(1, 0, 0)))
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.north, blockPos));
                    }
                }

                if (i % 16 == 1)
                {
                    //This is the SOUTH layer of the chunk.
                    if (!_loadedChunkObjs.ContainsKey(chunkObj.chunkPosition + new Vector3Int(-1, 0, 0)))
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.south, blockPos));
                    }
                }

                //This block is not within any of the faces.
                //Check each direction of the block
                if (i + 256 <= chunkData.blocks.Length)
                {
                    if (chunkData.blocks[i + 255] == 0) //TOP direction
                    {
                        //If the block ABOVE this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.top, blockPos));
                    }
                }

                if (i - 256 >= 0)
                {
                    if (chunkData.blocks[i - 256] == 0) //BOTTOM Direction
                    {
                        //If the block BELOW this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.bottom, blockPos));
                    }
                }

                if (i + 1 <= chunkData.blocks.Length - 1)
                {
                    if (chunkData.blocks[i + 1] == 0) //NORTH Direction
                    {
                        //If the block NORTH of this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.north, blockPos));
                    }
                }

                if (i - 1 >= 0)
                {
                    if (chunkData.blocks[i - 1] == 0) //SOUTH Direction
                    {
                        //If the block SOUTH of this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.south, blockPos));
                    }
                }

                if (i + 16 <= chunkData.blocks.Length)
                {
                    if (chunkData.blocks[i + 15] == 0) //WEST Direction
                    {
                        //If the block WEST of this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.west, blockPos));
                    }
                }

                if (i - 16 >= 0)
                {
                    if (chunkData.blocks[i - 16] == 0) //EAST Direction
                    {
                        //If the block EAST of this block is air then draw the face.
                        meshesToCombine.Add(GetMeshDataFromFace(Face.east, blockPos));
                    }
                }
            }
        }

        CombineInstance[] combine = new CombineInstance[meshesToCombine.Count];

        for (int i = 0; i < combine.Length; i++)
        {
            combine[i].mesh = meshesToCombine[i];
            combine[i].transform = chunkObj.transform.localToWorldMatrix;
        }

        mesh.CombineMeshes(combine);

        return mesh;
    }

If there are any necessary details I didn't include let me know and ill add them.

King Duck
  • 106
  • 2
  • 9
  • Try to draw single voxel, then two. I debugged it like this myself. Sadly, I can't give an example of how its done, because I did entire voxel chunks on bitmaps, instead or arrays (which is a lot faster and compact 64*64*64 will take 100 bytes regardless instead of 1 Mb and runs 10 times faster on mesh generation). – eocron Jul 04 '22 at 06:29
  • I can give you more insight on how its done in telegram @eocron if you interested. Its just too big for comments on stackoverflow. – eocron Jul 04 '22 at 06:43

0 Answers0