當前位置:歷史故事大全網 - 歷史天氣 - [Unity]拼接地块的随机地生成

[Unity]拼接地块的随机地生成

一个拼接地块生成随机的地图尝试过程,个人感觉效果不是很理想,还有很多优化空间,总之先记录一下。

虽然说是3D场景,但生成的地图块都在同一个平面上,严格地说依然是2D的思路。对于类似3D地牢的生成,官方已经有一篇文章介绍:在Unity中程序化生成的地牢环境。

整体思路:

缺点:

在一个场景中搭建好通用地块:

由于计划要烤夜光贴图,地块的开口作用就必须都是固定的的,旋转地块、拆除墙壁都会导致穿帮。当然也可以设置一些动态的墙壁,需要时通过拆除它们来形成开口。

上图搭建好的地块中,右侧两个主要地块,拥有2~4个方向的开口;中间四个小地块分成横向与垂直向,用于连接主要地块;左上角四个为单开口,在地块生成剩余后,用它们来封闭上空余的开口。

地大致搭完后将它们都具备预制体,进行烘烤。这里使用插件 Unity Lightmap Prefab Baker ,整个场景按当前的提示块进行烘烤,将烘烤出的提示贴图移动到指定文件夹,然后通过挂在预制体下的脚本记录关联的提示贴图,当预制体加载到新场景时将它们关联起来。

插件安装好后,每个地块预制体挂上PrefabBaker脚本:

Window -gt;Prefab Baker打开面板,调整相应设置后点击烘焙:

默认的提示贴图放在Assets/Resources/Lightmaps目录下,开发阶段可以暂时放在这里。如果2019版本报“无法创建资源”错误,可尝试修改Plugins/PrefabBaker/Scripts/EditorUtils.cs,在200行:

烘烤完成后:

为了让地块之间的开口处能够顺利对接上,地块的每个开口处需要放置一个空物体作为连接点,令两个地块的连接点重合即完成拼接。地块还需要有类型,这里分为了Room(房间,单开口), Corridor(走廊,东西或南北开口), Corner(拐角), TShaped(丁字), Hall(大厅,四面)开口)。

连接点,Z轴安装开口方向:

地块预制体:

拼接时需要能获取到地块的连接点情况,加入相关方法:

在一个新场景中生成地图,编写LevelGenerator.cs脚本:

先对地块预制体进行分类:

之后分好类开始生成,编写生成地图的方法GenerateLevel,由于需要多次将满足条件的对象放入列表来随机抽取,事先准备好一些列表避免反复创建:

先生成一个初始地块,这里选择走廊作为初始的地块,也可用其他的地块类型:

GetRandom 方法:

需要注意新场景中的灯光(主要是平行光)需要和烘焙场景保持一致。

当前的算法是逐个拼接生成地块,最后用单个开口地块对所有空余的开口进行闭合。为了控制地块数量,当前的地块数量为生成个数加上即将生成的个数。

编写循环生成:

GenerateMatchingCell方法用于寻找与当前地块连接口匹配的地块预制体,找到之后将它们拼接:

要寻找匹配的地块,首先要找到与当前连接点匹配的连接点类型:

然后在地块预制体中寻找包含该连接点类型的地块:

效果:

最后GenerateLevel方法中将有空余连接点的地块封口:

效果:

生成地形地块时,会发生冲突:

由于是逐个地块生成,冲突检测只能在要生成下一个地块时进行判断,如果当前连接点前方一段距离内已经存在地块,则该连接点不能用于继续生成,需要封闭;另外,如果连接点前沿不存在地块,还需要判断前沿的前沿、左方、右方是否存在地块,若存在则只能生成开口不同处的地块。

每个地块添加碰撞体:

LevelGenerator.cs加入冲突检测相关配置:

GenerateLevel方法中:

CheckConflict方法:

如果没有直接冲突,按照上面的逻辑判断前方的前方、左方、右方是否存在地块,若存在则记录到不期望的连接类型列表,另外由GenerateMatchingCell确定到GetMatchingCell中:

效果:

演示项目地址:

Procedural-Map-Demo

  • 上一篇:電泳現象證明了什麽
  • 下一篇:斯卡保羅集市的漢語歌詞是什麽
  • copyright 2024歷史故事大全網