|
最近专门研究了下程序化生成地形,其中最典型的莫过于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地形实现是从哪些方面来进行优化。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|