Unity C#生成Voxel Terrain的自定义网格未正确加载

发布于 2025-02-12 15:55:02 字数 10109 浏览 0 评论 0原文

因此,我正在创建类似于Minecraft的无限地形系统。我自己是出于个人兴趣来学习的。我最有用的所有东西,而且我做出了一些功能来生成立方体的面孔,然后将它们全部添加到一个块中,但是由于某种原因,我得到了一个非常奇怪的东西,其中每一行都是随机随机的比其他人高得多,破坏了整个网格。任何能够理解原因的人,因为我完全失去了这个问题。

注意:突出显示的部分应该是一个奇异的块,它延伸到整个块。它们的每组都落后于上一组,它应该是顶部完全平坦的脸。

// 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;
    }

块存储数据作为单数字节[] 4096索引的阵列。 这是生成网格的代码。

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;
    }

如果有任何必要的详细信息,我不包括让我知道并添加它们,

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文