ROAD_TYPE = stochastic_uneven
—— 随机不平路面
在ADAMS中的二维随机路面是根据路面文件按白噪声线性滤波法生成的左右两条轮辙纵剖面曲线。值得注意的是,在2003版(包括2003版)以前,MSC向用户提供的位于共享数据库中的随机不平路面示例文件mdi_2d_uneven.rdf是随第一个F-Tire一起败咐发布或消的,一直没有得到更新,如果用户要使用该文件作为模板则应修改PATH_CONSTANT的值为1000m(原为20)。
参数子数据块
这个值相当于H级道路
表 ROAD_TYPE = stochastic_uneven参数表参数
说明
START
随机不平路开始时的车辆行程
INTENSITY
按道路级别从ISO 8608选择空间功率谱密度的平均值计算其平方根,即 。例如,我们选择的随机不平道路的级别是B, 则Mean Value =4×10-6,
PATH_CONSTANT
高通滤波器截断频率路径表达量,默认值应为1000m。衫枯知
CORRELATION_RL
左右轮辙相关系数,在0~1之间,CORRELATION_RL=0表示不相关;CORRELATION_RL=1,左右轮辙相等。
表 ISO 8608道路分级标准
道路级别
G d(Ω0) [10-6m3]
Min. Value
Mean Value
Max. Value
A
-
1
2
B
2
4
8
C
8
16
32
D
32
64
128
E
128
256
512
F
512
1024
2048
G
2048
4096
8192
H
8129
16384
-
一个拼接地块生成随机地图的尝试过程,个人感觉效果不是非常理想,还有许多优化空间,总之先记录一下。
虽说是3D场景,但生察雀成的地图块都在同一个平面上,严格来说依然是2D的思路。对于类似3D地牢的生成,官方已经有一篇文章介绍: 在Unity中程序化生成的地牢环境 。
整体思路:
缺点:
在一个禅伍场景中搭建好各类地块:
由于计划要烘焙光照贴图,地块的开口朝向就必须都是固定的,旋转地块、移除墙壁都会导致穿帮。当然也可以设置一些动态的墙壁,需要时通过移除它们来形成开口。
上图搭建好的地块中,右侧两列为主要地块,拥有2~4个方向的开口;中间四个小地块分为横向与竖向,用来连接主要地块;左上角四个为单开口,在地块生成完毕后,用它们来封闭上空余的开口。
地块大致搭完后将它们都做成预制体,进行烘焙。这里使用插件 Unity Lightmap Prefab Baker ,它将整个场景按当前的光照设置进行烘焙,烘焙出的光照贴图移动到指定文件夹,然后通过挂在预制体下的脚本记录关联的光照贴图,当预制体加载到新场景时将它们关联起来。
插件安装好后,每个地块预制体挂上PrefabBaker脚本:
Window ->Prefab Baker 打开面板,调整相应设置后点击烘焙:
默认的光照贴图放在Assets/Resources/Lightmaps目录下,开发阶段可以暂时放在这里。如果2019版本报"Failed to created asset"错误,可尝试修改Plugins/PrefabBaker/Scripts/EditorUtils.cs,在200行:
烘焙完成后:
为了让地块之间的开口能顺利对接上,地块的每个开口处需要放置一个空对象作为连接点,令两个地块的连接点重合即完成拼接。地块还需要有类型,这里分为了Room(房间,单开口), Corridor(走廊,东西或南北开口), Corner(拐角), TShaped(丁字), Hall(大厅,四面开口败袭早)。
连接点,Z轴朝向开口方向:
地块预制体:
拼接时需要能获取到地块的连接点情况,加入相关方法:
在一个新场景中生成地图,编写 LevelGenerator.cs 脚本:
先对地块预制体进行分类:
分好类之后开始生成,编写生成地图的方法GenerateLevel,由于需要多次将满足条件的对象放入列表来随机抽取,事先准备好一些列表避免反复创建:
先生成一个初始地块,这里选择走廊作为初始的地块,也可用其他的地块类型:
GetRandom方法:
需要注意新场景中的光照(主要是平行光)需要和烘焙场景保持一致。
当前的算法是逐个拼接生成地块,最后用单开口地块对所有空余的开口进行封闭。为了控制地块数量,当前的地块数量为已生成个数加上即将生成个数。
编写循环生成:
GenerateMatchingCell方法用于寻找与当前地块连接口匹配的地块预制体,找到之后将它们拼接:
要寻找匹配的地块,首先要找到跟当前连接点匹配的连接点类型:
然后在地块预制体中寻找包含这种连接点类型的地块:
效果:
最后GenerateLevel方法中将有空余连接点的地块封口:
效果:
生成较多地块时,会发生冲突:
由于是逐个地块生成,冲突检测只能在要生成下一个地块时进行判断,如果当前连接点前方一段距离内已经存在地块,则该连接点不能用于继续生成,需要封闭;另外,如果连接点前方不存在地块,还需要判断前方的前方、左方、右方是否存在地块,若存在则只能生成开口朝向别处的地块。
每个地块添加碰撞体:
LevelGenerator.cs 加入冲突检测相关配置:
GenerateLevel方法中:
CheckConflict方法:
如果没有直接冲突,按照上面的逻辑判断前方的前方、左方、右方是否存在地块,若存在则记录到不期望的连接类型列表,随后由GenerateMatchingCell传入到GetMatchingCell中:
效果:
Demo项目地址:
Procedural-Map-Demo
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)