找回密码
 立即注册
查看: 165|回复: 0

Unity实现Minecraft(七)——Chunk脚本

[复制链接]
发表于 2022-10-25 15:55 | 显示全部楼层 |阅读模式
前言:前面一篇文章我们实现了ChunkRenderer脚本,主要是根据MeshData实现渲染。但是我们目前还没有任何一个类去填充MeshData(即MeshData的顶点List,三角形List等还没有数据)。所以我们将会在BlockHelper中进行MeshData的填充(因为BlockHelper是细化到Chunk中每个Block的每个面),而今天要写的Chunk脚本更像是一个辅助类去提供一些便利的方法供BlockHelper调用以便更好在Chunk内遍历时填充数据。
using System;
using UnityEngine;

public static class Chunk
{
    //遍历一个Chunk中的所有Block
    public static void LoopThroughTheBlocks(ChunkData chunkData, Action<int, int, int>
                                                                                                                                                                                        actionToPerform)
    {
        for (int index = 0; index < chunkData.blocks.Length; index++)
        {
            var position = GetPostitionFromIndex(chunkData, index);
            actionToPerform(position.x, position.y, position.z);//对方块进行的改变
        }
    }

    //一个根据block数组的index可以计算出相应block的(x,y,z)位置的算法(来源于StackOverFlow)
                /*      int zDirection=i%zLength;
                        int yDirection=(i/zLength)%yLength;
                        int xDirection=i/(ylength*zLength);
                */
    //根据Block的位置得到在Block数组中的位置
    private static Vector3Int GetPostitionFromIndex(ChunkData chunkData, int index)
    {
        int x = index % chunkData.chunkSize;
        int y = (index / chunkData.chunkSize) % chunkData.chunkHeight;
        int z = index / (chunkData.chunkSize * chunkData.chunkHeight);
        return new Vector3Int(x, y, z);
    }

    //在Chunk坐标系下
    //判断Block是否超出所属Chunk的界限
    private static bool InRange(ChunkData chunkData, int axisCoordinate)
    {
        if (axisCoordinate < 0 || axisCoordinate >= chunkData.chunkSize)
            return false;

        return true;
    }

    //同上
    private static bool InRangeHeight(ChunkData chunkData, int ycoordinate)
    {
        if (ycoordinate < 0 || ycoordinate >= chunkData.chunkHeight)
            return false;

        return true;
    }
    //根据Chunk坐标系的坐标得出该Block的类型
    public static BlockType GetBlockFromChunkCoordinates(ChunkData chunkData, Vector3Int chunkCoordinates)
                                                                                                                                                                                                                                Vector3Int chunkCoordinates)
    {
        return GetBlockFromChunkCoordinates(chunkData, chunkCoordinates.x, chunkCoordinates.y,chunkCoordinates.z);
                                                                                                                                                                                        chunkCoordinates.z);
    }
  
    public static BlockType GetBlockFromChunkCoordinates(ChunkData chunkData, int x, int y, int z)
    {
        if (InRange(chunkData, x) && InRangeHeight(chunkData, y) && InRange(chunkData, z))
        {
            int index = GetIndexFromPosition(chunkData, x, y, z);
            return chunkData.blocks[index];
        }

        return chunkData.worldReference.GetBlockFromChunkCoordinates(chunkData, chunkData.worldPosition.x + x, chunkData.worldPosition.y + y, chunkData.worldPosition.z + z);
    }
    //设置Block的类型
    public static void SetBlock(ChunkData chunkData, Vector3Int localPosition, BlockType block)
    {
        if (InRange(chunkData, localPosition.x) && InRangeHeight(chunkData, localPosition.y) && InRange(chunkData, localPosition.z))
        {
            int index = GetIndexFromPosition(chunkData, localPosition.x, localPosition.y, localPosition.z);
            chunkData.blocks[index] = block;
        }
        else
        {
            throw new Exception("Need to ask World for appropiate chunk");
        }
    }
    //从一个Block的坐标得到在数组中的位置
    /*i (x,y,z)
                        0 (0,0,0)
                        1 (0,0,1)
                        2 (0,0,2)
                        3 (0,1,0)
                        4 (0,1,1)
                  5 (0,1,2)
                        6 (0,2,0)
                        ......
                        19 (2,0,1)
                        26 (2,2,2)
                        i=z+y*ZSize+x*ZSize*YSize*/
    private static int GetIndexFromPosition(ChunkData chunkData, int x, int y, int z)
    {
        return x + chunkData.chunkSize * y + chunkData.chunkSize * chunkData.chunkHeight * z;
    }
    //根据Chunk坐标系的坐标得到对应的Block
    public static Vector3Int GetBlockInChunkCoordinates(ChunkData chunkData, Vector3Int pos)
    {
        return new Vector3Int
        {
            x = pos.x - chunkData.worldPosition.x,
            y = pos.y - chunkData.worldPosition.y,
            z = pos.z - chunkData.worldPosition.z
        };
    }
    //获得MeshData的方法
    public static MeshData GetChunkMeshData(ChunkData chunkData)
    {
        MeshData meshData = new MeshData(true);

        LoopThroughTheBlocks(chunkData, (x, y, z) => meshData = BlockHelper.GetMeshData(chunkData, x, y, z, meshData, chunkData.blocks[GetIndexFromPosition(chunkData, x, y, z)]));


        return meshData;
    }
   
    internal static Vector3Int ChunkPositionFromBlockCoords(World world, int x, int y, int z)
    {
        Vector3Int pos = new Vector3Int
        {
            x = Mathf.FloorToInt(x / (float)world.chunkSize) * world.chunkSize,
            y = Mathf.FloorToInt(y / (float)world.chunkHeight) * world.chunkHeight,
            z = Mathf.FloorToInt(z / (float)world.chunkSize) * world.chunkSize
        };
        return pos;
    }
}
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-21 20:41 , Processed in 0.091644 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表