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

Unity实现Minecraft(一)——原理介绍

[复制链接]
发表于 2022-10-9 09:12 | 显示全部楼层 |阅读模式
       最近专门研究了下程序化生成地形,其中最典型的莫过于Minecraft中的地形生成,于是打算自己实现一下。闲话少说,游戏引擎:(2021.2) 。
       ①先来简单介绍原理:利用一个二重循环生成一个网格地图,然后对于每一个网格的位置坐标生成一个噪声值(噪声值介于0和1之间),然后乘以一个自己定义的高度值Height,就会得到一个(0,Height)的值;然后再用一个循环从0到Height,每个高度放置方块即可。
注意:我们规定每一个单位的方块叫Block,后面也可以叫它体素(Voxel)。
      ②在Unity模拟一下过程:
using System.Collections.Generic;
using UnityEngine;
using System;

namespace Test
{
    public class ProceduralTerrain : MonoBehaviour
    {
        [SerializeField] private float noiseScale = 0.05f;
        [SerializeField] private int worldSize = 6;
        [SerializeField] private int worldHeight = 10;
        [SerializeField] private int waterHeight = 4;
        //用于保存每个Block类型的颜色
        private Dictionary<t_BlockType, Color> colorDic = new Dictionary<t_BlockType, Color>();
        
        private void Awake()
        {
            //将Block的材质和颜色一一对应
            colorDic.Add(t_BlockType.Grass_Dirt, Color.green);//草方块对应绿色
            colorDic.Add(t_BlockType.Dirt, Color.yellow);//泥土对应黄色
            colorDic.Add(t_BlockType.Water, Color.blue);//水对应蓝色
            colorDic.Add(t_BlockType.Sand, Color.gray);//沙对应灰色
        }
        private void Start()
        {
            GenerateTerrainData();
           
        }
        private List<t_BlockData> worldBlockData = new List<t_BlockData>();
        //生成地形所需数据,就是求出一个每个坐标的高度值
        void GenerateTerrainData()
        {
            t_BlockType blockType;
            for (int i = 0; i < worldSize; i++)
            {
                for (int j = 0; j < worldSize; j++)
                {
                    float noiseValue = Mathf.PerlinNoise((transform.position.x + i) * noiseScale, (transform.position.z + j) * noiseScale);
                    int groundPosition = Mathf.RoundToInt(noiseValue * worldHeight);
                    for (int y = 0; y < worldHeight; y++)
                    {
                        blockType = t_BlockType.Dirt;
                        if (y > groundPosition)
                        {
                            if (y < waterHeight)
                            {
                                blockType = t_BlockType.Water;
                            }
                            else
                            {
                                blockType = t_BlockType.Air;
                            }

                        }
                        else if (y == groundPosition && y < waterHeight)
                        {
                            blockType = t_BlockType.Sand;
                        }
                        else if (y == groundPosition)
                        {
                            blockType = t_BlockType.Grass_Dirt;
                        }

                        t_BlockData temp = new t_BlockData(new Vector3(transform.position.x + i, y, transform.position.z + j), blockType);
                        worldBlockData.Add(temp);
                    }
                }
            }
        }
        //用Gizmos来模拟生成的地形
        private void OnDrawGizmos()
        {
            if (worldBlockData.Count > 0)
            {
                foreach (var block in worldBlockData)
                {
                    if (block.blockType == t_BlockType.Air)
                    {
                        continue;
                    }
                    Gizmos.color = colorDic[block.blockType];
                    Gizmos.DrawCube(block.blockPosition,new Vector3(1f,1f,1f));
                }
            }
            
        }
    }

    internal class t_BlockData
    {
        public Vector3 blockPosition;
        public t_BlockType blockType;

        public t_BlockData(Vector3 position,t_BlockType type)
        {
            blockPosition = position;
            blockType = type;
        }
    }
    internal enum t_BlockType
    {
        None,
        Air,
        Grass_Dirt,
        Dirt,
        Sand,
        Water
    };
}




    ③总结:这样就简单完成了一个模拟过程,但这样有一个很明显的问题,一旦我们的地形过大就会导致游戏帧率下降,影响游戏体验,所以我们下一篇文章就来讲讲真正的Minecraft地形实现是从哪些方面来进行优化。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-9-21 21:59 , Processed in 0.097083 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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