Mesh地形生成,切割,保存为文件

本文介绍了在Unity中如何使用Mesh进行地形生成,包括根据灰度图创建Mesh,对Mesh进行切割以适应大小限制,解决切割后可能出现的缝隙问题,并详细说明了如何将生成的Mesh保存为文件。此外,还提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果展示:
在这里插入图片描述
在这里插入图片描述
可直接使用的完整代码在本文最后

工具介绍:

工具

  1. Auto Cutting属性,勾选该属性后,Each Terrain Size属性失效,脚本会根据Terrain Size属性自动划分网格,单个网格大小不会大于256*256.
  2. Height Map属性用来存放灰度图
  3. Terrain Height、Terrain Size 用来指定mesh的高度和大小
  4. 在Auto Cutting属性未勾选的情况下, Each Terrain Size属性可以用来指定每块地图的大小,属性要求必须能被TerrainSize整除
  5. Terrain Mat规定了地形的材质
  6. Origin属性为Mesh的父对象,可为空,默认为脚本所在对象
  7. 勾选Create Prefab属性,会将动态生成的Mesh文件保存为Prefab,在Assets文件夹下
Mesh基础知识:

https://catlikecoding.com/unity/tutorials/procedural-grid/

根据灰度图生成Mesh

在读取图像之前,务必勾选Read/Write Enable属性
在这里插入图片描述
单张Mesh的话,我们需要做的只是对它顶点坐标的Y值做一些手脚

 vertices.Add(new Vector3(i, HeightMap.GetPixel(X,Y).grayscale * TerrainHeight,j));

HeightMap.GetPixel((int)a,(int)b).grayscale;可以对图像灰度值进行采样

对Mesh进行切割

由于Mesh的限制,单张Mesh大小不能大于256*256,而且,我们通常不会把整个地图全部加载出来,地图分块是必须的
所谓切割,其实就是分批对灰度图采样

vertices.Add(new Vector3(TX*EachTerrainSize+i, HeightMap.GetPixel(X,Y).grayscale * TerrainHeight, TY*EachTerrainSize+j));

需要注意,无论TerrainSize值为多少,整张灰度图都会被利用到,就是说,在采样之前有一个缩放的过程

int X =(int)((float)TX * (float)EachTerrainSize *((float)MapWidth/(float)TerrainSize) + (float)i * ((float)MapWidth / (float)TerrainSize));
int Y = (int)((float)TY * (float)EachTerrainSize *((float)MapHeight / (float)TerrainSize) + (float)j * ((float)MapHeight / (float)TerrainSize));
Mesh切割之后有缝隙问题

这是因为,两个相邻的Mesh中间的连线并没有连接起来
在这里插入图片描述
我的做法是,规定255*255为最大单片Mesh大小,剩下的预留,用来补间,排除不需要补间的情况

			List<Vector3> vertices = new List<Vector3>();
            List<int> triangles = new List<int>();
            //只有在单片Mesh(不切割)的情况下,EachTerrainSize才有可能==256
            int EachTerrainSize_1 = EachTerrainSize == 256 ? 256 : EachTerrainSize + 1;
            for (int i = 0; i < EachTerrainSize_1; i++)
            {
   
   
                for (int j = 0; j < EachTerrainSize_1; j++)
                {
   
   
                    if (j == EachTerrainSize_1 && TX >= MAXXY-1)
                    {
   
   
                        break;
                    }
                    if (i == EachTerrainSize_1 && TY >= MAXXY - 1)
                    {
   
   
                        break;
                    }
                    int X =(int)((float)TX * (float)EachTerrainSize *((float)MapWidth/(float)TerrainSize) + (float)i * ((float)MapWidth / (float)TerrainSize));
                    int Y = (int)((float)TY * (float)EachTerrainSize *((float)MapHeight / (float)TerrainSize) + (float)j * ((float)MapHeight / (float)TerrainSize));
                    vertices.Add(new Vector3(TX*EachTerrainSize+i, HeightMap.GetPixel(X,Y).grayscale * TerrainHeight, TY*EachTerrainSize+j));
                    if (i == 0 || j == 0) continue;
                    triangles.Add(EachTerrainSize_1 * i + j);
                    triangles.Add(EachTerrainSize_1 * i + j 
切片过程 1)开始切片过程,在Unity编辑器顶部选择地形选项,然后单击“切片地形”选项。一个窗口会出现一些配置信息。 2)拖动您希望分割为“地形切片”字段的地形。或者,如果您在步骤1中单击“切片地形”选项时选择了地形,则该字段中已经出现了地形。 3)输入每个补丁的详细分辨率。优选地,该值应与每个补丁值的基本地形细节分辨率匹配。这些信息不能通过脚本访问,这就是为什么你必须在这里输入它。您可以输入与基础地形设置不同的值,但这将导致细节网格(植物和草地)复制的准确性降低。 4)选择您希望结束的切片维度。2×2仅仅意味着基本地形将沿着X轴2次和Z轴2次分割,以创建4个地形片。64×64未经测试,不建议使用,所以请自行承担风险。 5)设置希望存储地形数据的文件路径。默认情况下,这是资产/ terrainslicing /地形数据。如果您希望暂时在另一个文件夹中创建地形数据,只需在这里输入新路径。如果希望永久更改默认文件夹,请输入新的文件路径,并选择“保存当前文件路径作为默认文件路径”按钮。请确保没有“/”后的文件路径上的文件夹名称(例如,用于文件的默认路径的地形数据后),否则将会出现错误。 6)当单击“创建地形”按钮时,选择是否覆盖现有的地形数据。这是一个安全功能,以确保你不小心覆盖的地形数据,你已经创造了。如果试图在未选中此值时重写数据,则会出现警告消息,告诉您要检查此值,而切片操作将不会开始。 7)单击“创建地形”按钮,等待进度条填充。如果进度条未显示,则在编辑器窗口显示通知错误的通知消息。有时您可能需要检查控制台以获得更详细的信息。最后,确保只在编辑模式下执行切片地形脚本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值