rustum 发表于 2022-10-9 09:12

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

       最近专门研究了下程序化生成地形,其中最典型的莫过于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
    {
       private float noiseScale = 0.05f;
       private int worldSize = 6;
       private int worldHeight = 10;
       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;
                  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地形实现是从哪些方面来进行优化。
页: [1]
查看完整版本: Unity实现Minecraft(一)——原理介绍