网页版
https://yekdniwue.blogspot.com/2020/07/GenNavMesh1.html
简介
使用先前提供的做法,把现实世界的地形档汇入UE4之后,
画面表现正常了,地图也会根据设定的streaming distance运作。
下一个目标就是让AI角色能在这块地形正常的跨区域移动。
但是我很快就遇到两个问题:
1. 在play in editor遇到新的地图加载的时候卡顿。
2. Navigation mesh要build 超久
首先是我在play in editor内,只要遇到地图档读取就会造成卡顿,
但是我的地图档除了地形跟navigation mesh之外,
没有放置其他的物件。
再来就是在build navigation mesh的时候超级慢,
Build一张要5分钟以上,并且会伴随很多的warning。
我做了不少的实验想要尝试改善这些问题,但是最后都是失败的。例如:
降低地形复杂度
一开始我有尝试用Flatten tool把地形辗平,也没有加快Build path的速度。
代表地形的复杂度不影响build path以及loading的速度(或是差异不够大)。
维持分割地图数,降低height map分辨率
将每一张tiled height map分辨率输出的时候从2017*2017降为505*505,
没有差很多,但是地形大小不一样了,不符合我的实验。
效能改善的基本重点,当然是希望输入输出尽可能一样,改了就不对了。
维持总分辨率几乎一致,分割地图数变多。
例如原来是一张大地图档输出成4*4张tiled map(2017*2017)。
改为一张大地图档输出成9*9张tiled map(505*505)。
可想而知,每一张地图都变小了,应该可以有效增加分辨率,
但是原来只要build 16个level的navigation mesh。
现在变成要build 81次...
手动操作一两张地图测试后,确定是可以降低读取时间。
不过以人工来说过于费时。需要靠程式批次处理。
因为navigaion mesh存在各个子地图会增加地图档大小,
有可能读取卡顿问题也跟资源变大有关。
最后发现UE4提供不少产生navigation mesh的用法,
于是研究一下各种方法的优缺点,或许可以解决读取问题。
Navigation Mesh in World Composition.
Unreal总共有以下几种Navigation的使用方法,以下列出详细的操作步骤。
产生Navigation Mesh的操作流程
1. Static NavMesh
通常用在关卡式的地图,一个关卡就设置一个Navigation Bounds Volume
(以下简称NBV)
整个NBV就是罩住整个场景,然后在Editor点选Build Path,
储存有NBV的地图,这样就完成了。
2. Static NavMesh with World Composition
在文章中有提到使用World Composition也可以读取static NavMesh。
做法如下:
1. 在主地图放置一个NBV,可以不用罩住任何东西。
2. 自动产生于主地图的RecastNavMesh-Default内,
有个属性Runtime Generation设为Static。
3. 在Levels内读取每个子地图,放置各自的NBV,
并且罩住所需要的区域。
4. 执行Build path。navigation mesh资讯就会存入子地图。
3. Dynamic NavMesh with World Composition
1. 在主地图放置一个NBV,罩住全地图范围。
2. Editor Preferences->Level Editor->Miscellaneous->
Update Navigation Automatically设为false
3. 自动产生于主地图的RecastNavMesh-Default内,
有个属性Runtime Generation设为Dynamic。
4. Navigation mesh就会在地图加载后,
开始自动计算并产生navigation mesh。
4. Lazy Dynamic NavMesh with World Composition
1. 在主地图放置一个NBV,罩住全地图范围。
2. Editor Preferences->Level Editor->Miscellaneous->
Update Navigation Automatically设为false
3. 自动产生于主地图的RecastNavMesh-Default内,
有个属性Runtime Generation设为Dynamic。
4. Project Settings->Navigation System->
Data Gathering Mode 设为Lazy
5. Generate Navigation Only Around Navigation Invokers
设为true
6. 在AI pawn的class 新增NavigationInvokerComponent
验证时需注意的事项
在测试Navigation mesh的时候,最好把editor重开后,
再看一次是不是正确显示。
我有遇到Build path后有navigation mesh,PIE也正常,
但是重新开启editor后,
navigation mesh就消失不显示的情况。
Static NavMesh
Static NavMesh是常见关卡式的作法,其实用在World Composition也可以。
但是这个做法会把nav mesh全部存入主地图,等于一开始读取主地图后,
整个世界的navmesh都会被加载。
主地图的档案大小会很大,也会严重影响到初始读取的速度。
Static NavMesh with World Composition
官方说这个方法可行,但是我测试(环境是UE 4.23)的结果是,
只有第一个sublevel(通常是X0_Y0那一张)有被读取的时候,
static navimesh才会正常运作。
举例来说,
玩家在地图X0_Y0往X0_Y1的地图走,当触发X0_Y1读取的时候,
X0_Y0以及X0_Y1两张地图的navigation mesh都是正常的。
但是继续走到X0_Y0会被unload的距离时,
全部的navigation mesh都会跟着被unload。
目前我还没有找到解决的方法,不过可以知道的是就算解决了,
这种静态navigation mesh的作法仍然有一些问题,
这边就列出使用static navigation mesh的优缺点。
优点
资料完全静态,在游戏中完全不需要花时间计算nav mesh。
缺点
静态navigation mesh资料存在每张tiled level内,所以会增加读取时间。
场景内容有更改就要重build navigation mesh,
开发过程要持续维护,不然AI移动会有问题。
Dynamic NavMesh with World Composition
这个方法验证后可以正确运作,但是在地形比较大的环境,会有严重的FPS下降的情况。
主因当然就是因为动态在计算大片的navigation mesh造成的。
如下图,较大的地形被加载时需要大量的计算。
[图]
Lazy Dynamic NavMesh with World Composition
目前个人觉得可以接受的解决方案,只有在AI角色所在的区域,
会即时计算navigation mesh,如下图。
[图]
实际用起来不太会感受到CPU在计算navigation mesh的延迟。
不过还是有一些缺点或是小细项是需要注意的。
因为是动态navigation mesh,所以不容易在editor模式,
预览navigation有问题的情况。
不好预览自然就不方便修正。
角色invoker的范围要怎么订,是要考虑角色大小、移动速度、
移动范围等参数的。
角色移动速度过快,造成nav mesh计算不及,就会移动失败。
角色移动范围大于产生的nav mesh,也会形成移动失败。
大量的角色会分散在各个地图中,并且来回走动。
这样的案例应该会比Dynamic NavMesh with World Composition还差。
因为来回走动造成算过的navigation mesh重复计算了(未实际验证)。
同上,移动速度较快的角色,
也容易持续触发动态navigation mesh的计算。
影响CPU执行时间。
结论
上面列出了我最近有测试过开放场景的navigation mesh用法。
static navigation mesh的版本看起来如果没有bug的话,还是很泛用,毕竟没有任何动
态的资源会被浪费。
但是以现在的实作版本,看起来选择Lazy dynamic mesh是比较好的选择。
参考资料
https://forums.unrealengine.com/development-discussion/content-creation/96325-static-navmeshes-and-level-streaming?123887-Static-NavMeshes-and-Level-Streaming=
StaticNavmesh and level streaming
这两篇的人跟我一样想要尝试使用static nav mesh,但是失败了。
https://forums.unrealengine.com/development-discussion/content-creation/24862-how-to-work-with-navmesh-and-big-landscapes?54116-How-to-work-with-NavMesh-and-big-Landscapes=
How to work with NavMesh and big Landscapes?
这篇最后有人提到使用Navigatiohn invoker使用的方法