Nav Mesh生成耗时很高

Hi,

因为我们场景中存在可破坏的障碍物,所以在WP场景中使用动态了Nav Mesh,并且使用了Nav Mesh invoker。

场景里面是用了一个大的NavMeshBoundsVolume包裹起来的。

[Image Removed]然后添加了一些Nav Modifier Volume 不过没有设置nav mesh resolution。默认情况下,没有设置的话,应该就是读config里面的吧?这个我不太了解,所以还是询问一下。

[Image Removed]RecastNavMesh也是一开始的默认值,没有改动过。这个应该也是直接被config里面的设置覆盖了吧? 我不太清楚他和config里面的优先级哪个更高一些,是关卡里面的优先级高,还是config里面的优先级更高?

[Image Removed]

然后给invoker设置了一个范围:

[Image Removed]

但是打包测试发现,Nav Mesh的耗时很高。

[Image Removed]使用stat navigation也发现Recast do work, build compressed layers,rasterize triangles一直飙升

[Image Removed]在config里我们是设置了这些:

[/Script/NavigationSystem.NavigationSystemV1]
bAutoCreateNavigationData=True
DataGatheringMode=Lazy
bGenerateNavigationOnlyAroundNavigationInvokers=True
ActiveTilesUpdateInterval=2.000000
 
[/Script/NavigationSystem.RecastNavMesh]
CellSize=19.000000
CellHeight=10.000000
AgentRadius=35.000000
ObservedPathsTickInterval=1.000000
bDrawPolyEdges=False
bDoFullyAsyncNavDataGathering=False
RuntimeGeneration=Dynamic
TileSizeUU=1216

我们想了解下在WP的场景下,有什么优化方式么?或者说在WP下,存在可破坏的障碍物这种,最佳的设置Nav Mesh的方式应该是怎样的?

这里是一个Unreal Insights抓的Trace数据,也提供一下:

https://drive.google.com/file/d/1Rg-jm8zGpPf6REsja-3YjZCOa_z-nsGi/view?usp=sharing

另外还有一个问题,我们发现某些特效用到的模型,似乎对导航网格也有影响。 在怪物播放一个特效的时候,导航网格会变红一下。

我知道普通的Mesh,可以关闭Can Ever Affect Navigation

[Image Removed]但是没在场景里面的Mesh没有这个选项。

特效里面是用了Mesh Renderer

[Image Removed]我发现找到Mesh Renderer里面的模型,关闭这个似乎就不受影响了。

[Image Removed]关闭以后,怪物在播放特效的时候,导航网格一直会保持绿色。

我印象中特效应该是不会影响导航网格的,不知道为什么会有影响。 也不知道关闭这个设置是否正确,所以想询问一下。

更新一下:

我们后面又测试了一下,发现好像不是特效mesh影响到的导航网格,是背后有个可破坏障碍物导致的。 找了一个没有可破坏物的区域就正常了。

之前倒是碰到过Niagara特效影响的情况,是在Niagara用了Geometry Cache Renderer 这个会影响导航网格

[Image Removed]但是发现这个在资产层面没办法改碰撞之类的,后来是把引擎改了。不知道 这个是否有更好的方式去解决。

[Image Removed]因为之前的例子,所以想当然以为是一样的情况了。 最后发现好像不是。

把has navigation data还原也不会再出现把nav mesh变脏的情况了。 不过想问一下Niagara的Mesh把这个has navigation data关掉应该也没什么影响吧?

另外就是想了解下如果Niagara用到的模型没有关闭碰撞,是否会对Nav Mesh造成影响呢?我怕测试的不太全面,保险起见还是问一下。 还有就是 是否所有的Niagara特效用到的Mesh,都应该关闭碰撞呢?

[Content removed]

锁定导航网格和解锁的操作,想请问下这个具体是怎么操作的呢?没有看到相关的文档。

Hi,

感谢您的解答。有点小的疑问。

1. Nav Modifier Volume那个,我没有设置nav mesh resolution,他默认设置是None,是读哪里的设置呢?是直接读config的么?

[Image Removed]我在config当中只设置了这些,没有包含针对Low,Default,High单独调整。所以针对这个分辨率,有点疑惑会读哪个数据。 我不太清楚正确的设置方式应该是怎样的,是需要单独给low,default,high去进行设置,还是给Modifier选择一个质量档位么? 还是我在config中,有一个全局设置就可以了?

[/Script/NavigationSystem.RecastNavMesh]
CellSize=19.000000
CellHeight=10.000000
AgentRadius=35.000000
ObservedPathsTickInterval=1.000000
bDrawPolyEdges=False
bDoFullyAsyncNavDataGathering=False
RuntimeGeneration=Dynamic
TileSizeUU=1216

2.您提到的"config可以理解为全局的默认值,对象初始化时会通过config值进行覆盖,然而,在场景中的对象拖到场景中时会经过初始化的流程生成一个实例,通过属性面板设置的值是修改实例的值并序列化到场景中。因此通过属性面板的值优先于config,最终以属性面板为准"

这个是否我可以理解为,如果我没有修改RecastNavMesh的默认值,他会读取我config里面的设置,如果我修改了RecastNavMesh的值,他会以RecastNavMesh属性面板的值为准?

3.关于Dynamic Obstacle,我发现场景中的静态网格体好像并没有这个选项,只有进入到Static Mesh的编辑界面才有一个is Dynamic Obstacled的标记,静态网格体如果需要标记的话,是需要打开Static Mesh编辑器去设置的么?

4.避免在一瞬间大量可破碎物体生成触发一大片tiles的重建

这个解决办法是指设置Dynamic Obstacle么?还是什么其他的?

5.您提到的"可以限制tile的size来避免大块tile的重建时间较长"。

是指我在config当中设置的这部分么?

[/Script/NavigationSystem.RecastNavMesh]
CellSize=19.000000
CellHeight=10.000000
AgentRadius=35.000000
ObservedPathsTickInterval=1.000000
bDrawPolyEdges=False
bDoFullyAsyncNavDataGathering=False
RuntimeGeneration=Dynamic
TileSizeUU=1216

6.关于Niagara那部分,如果不是拖放在场景中的NiagaraActor,是程序动态生成的。没有Can Ever Affect Navigation之类的设置,是否有什么其他的操作要处理呢?

您好,涉及到几个问题

​RecastNavMesh在config的值和在场景中通过属性面板哪个优先级更高:

config可以理解为全局的默认值,对象初始化时会通过config值进行覆盖,然而,在场景中的对象拖到场景中时会经过初始化的流程生成一个实例,通过属性面板设置的值是修改实例的值并序列化到场景中。因此通过属性面板的值优先于config,最终以属性面板为准

对于可破碎障碍物的优化:

你可以看下将物体标记为 “Dynamic Obstacle”这种方式。被标记为动态障碍的物体不会触发整个导航tiles重建,而只在其周围标记需要更新的区域​

同时避免在一瞬间大量可破碎物体生成触发一大片tiles的重建,一方面可以限制tile的size来避免大块tile的重建时间较长,另一方面,在tile重建时需要确定究竟是哪个actor影响导致的,从unreal insight是看不出来的,建议通过

在log输入log LogNavigation Verbose,此时在日志会显示出影响​导航的详细信息,在运行时会显示此时哪个actor的哪个组件影响了导航

从insight看是主线程的geometry gathering阶段的瓶颈,您试下打开异步线程收集bDoFullyAsyncNavDataGathering看看会不会有改善​

锁定导航网格和解锁:

主要用于一次性加载大量关卡内容或障碍物时,可以暂时锁定导航网格自动更新,等批量加载完成后再一次性解锁更新。​参考下这个链接的介绍

https://dev.epicgames.com/documentation/en\-us/unreal\-engine/optimizing\-navigation\-mesh\-generation\-speed\-in\-unreal\-engine

对​Niagara如果是纯视觉表现不影响导航应该关闭拖到场景的NiagaraActor中的Can Ever Affect Navigation属性,同时如果不需要额外的导航数据也建议关闭has navigation data

1.nav mesh resolution对于不同精度的设置是在project settings里面NavigationMesh里面的NavMeshRolutionParams去设置不同精度,当然也可以在场景的recast里设置NavMeshRolutionParams,读的就是这个值,Cell size设置越大,生成速度越快,这样Nav Modifier component就可以根据需求设置什么精度的分辨率去生成,比如场景很大很空旷,可以默认用低精度去生成导航数据,但是对于一些需要高精度的某些区域比如建筑河流,可以在这个位置加一个Nav Modifier component设置为高精度去生成导航数据,只针对这部分区域的导航数据使用高精度,这样可以减少整个场景中生成导航数据的内存

这是官方的介绍文档可以参考下

https://dev.epicgames.com/documentation/en\-us/unreal\-engine/navigation\-mesh\-resolutions\-user\-guide

2.是的

3.是的

4.是指通过监控LogNavigation来确认在每个瞬间哪些actor影响了导航,这些actor是否有必要开启can ever affact navigation,如果需要开,看看能不能避免都在同一帧生成,这样会导致一瞬间在大片区域上影响导航重建,导致出现瞬时卡顿

5.是这个值TileSizeUU

6.如果不是拖放在场景中的NiagaraActor,是程序动态生成的。这个动态生成的组件Component->SetCanEverAffectNavigation(false)

1.那么如果像这个一样,Nav Modifier设置的是None呢?他是完全不生效,还是会读取的什么值?是必须要设置一个low,default或者high的参数么?

[Image Removed]2.关于6 提到的那个,程序动态生成的,是需要手动设置Component->SetCanEverAffectNavigation(false)么?还是引擎其实默认就是SetCanEverAffectNavigation(false) 不需要人工去管?

3.还有一个问题 就是我们的Nav Mesh是Dynamic的 目前是在场景里面是用了一个大的NavMeshBoundsVolume包裹起来的 这个是否可以呢? 还是要拆分开多个NavMeshBoundsVolume更符合标准一些? 我不确定Dynamic的Nav Mesh是否是添加一个大的NavMeshBoundsVolume包裹起来比添加多个更好一些。

[Image Removed]

1.如果Nav Modifier设置的是None,我的理解读取的就是RecastNavMesh默认的cellsize,可以通过ini去指定

2.对于基类的bCanEverAffectNavigation在构造会默认false,但是子类某些组件在构造默认设为true,比如MeshComp,ShapeComp等,所以需要看最后生成的组件是什么类型的组件,如果不需要影响导航,对于MeshComp这种就需要手动设置一下

3.一般建议用一个很大的nav volume包裹起来所有navigation invoker所有可能的移动范围即可,因为是动态导航,只会在invoker半径内生成导航数据,拆成多个nav volume一般是ue4流关卡的做法,不同流关卡用不同volume包裹提前烘焙好,在流送的时候把那部分数据加进来

1.也就是说,默认情况下,他会读取RecastNavMesh里面Default的值,或者是ini里面的值呗。

2.我指的是Niagara的动态生成,比如Spawn一个Niagara之类的。我的印象里,Niagara这部分好像没有MeshComp,ShapeComp之类的吧。传统Actor的Comp我知道是会有这种东西的。

3.明白了,非常感谢。

对于第一个我又看了一下,FPImplRecastNavMesh::Serialize中

会去查下NavMeshVersion这个版本,如果是很旧的版本,就会走没有resolution的流程从recast默认cellsize去读取,如果是最新的版本,就直接从ENavigationDataResolution::Default去拿了

第二个我要不再帮你确认一下,晚点回复您

1.您说的这个​NavMeshVersion旧版本,是指以前引擎版本创建的RecastNavMesh么?我印象中以前版本的RecastNavMesh好像是没有low,high default之类的,只有一个默认设置。这个旧版本和新版本怎么区分呢?是看参数是否有low high default之类的么?

最新的版本,是直接读取Default的值,也就是说不会去读ini么?还是如果ini配置了,就会去读ini,没配置的话,就默认去读Default的值。

2.好的 麻烦您了 感谢:)

1.是的,不同版本在RecastVersion.h中设置的navmesh版本不一样,在保存关卡后会把这个值序列化进去,新的引擎版本读取旧的关卡的值得到的navmesh版本也是不一样的

2.Niagara默认不会影响导航,不清楚您说的为什么会影响,按理说内部的NiagaraComponent默认也不会影响导航,如果你们有这种问题,可以按照我说的之前的log方式去查一下是否有别的actor影响导致的

关于这个,我再确认一下:“如果是最新的版本,就直接从ENavigationDataResolution::Default去拿了

如果我在config里面配置了全局的这个设置,Nav Modifier为None的情况下,是会读config么?还是说它不管config,直接从RecastNavMesh里面直接拿Default的值了。

[/Script/NavigationSystem.RecastNavMesh]
CellSize=19.000000
CellHeight=10.000000
AgentRadius=35.000000

我个人的理解是,默认情况下读config的值,如果RecastNavMesh的Default里面有修改了,在Nav Modifier为None的情况下,会以场景中已修改的RecastNavMesh的Default值为准。

不过如果我已经指定了Nav Modifier为Low,那么他会直接读RecastNavMesh中Low的值,直接忽略config的设置?还是说会以config的为主?这个我不太确定。

感谢提醒,为None的情况从DefaultEngine.ini去拿默认值,不是从ENavigationDataResolution::Default去拿,

如果指定了Nav Modifier为Low,会以低分辨率设置的值为准,但如果同一位置重叠了多个Modifier时,一个为低分辨率,一个为高分辨率,会以最高的分辨率为准

非常感谢您的解答。那么还有一个小的疑问点。

为None的情况从DefaultEngine.ini去拿默认值,不是从ENavigationDataResolution::Default去拿

那么比如说Nav Modifier为None的情况下,我config里面已经设置了默认值,那么如果这个时候我改动了RecastNavMesh中Default的默认值,他是会继续读Config,还是会读RecastNavMesh的呢?因为您提到一个ENavigationDataResolution::Default,我的理解如果config不是第一优先级的情况下,应该就是读RecastNavMesh里面Default的值了吧。在前面的回答中,我印象里好像是RecastNavMesh的优先级更高一些。 所以不太确定,如果在RecastNavMesh已经修改的前提下,config和RecastNavMesh的优先级是怎样的。

另外我记得官方说过FN也是用了Dynamic的Nav Mesh。

可以分享一下FN有关于NavMesh的Config设置么

主要是这两个部分的:

[/Script/NavigationSystem.NavigationSystemV1]
 
[/Script/NavigationSystem.RecastNavMesh]

1.在编辑器启动时recast这个类第一次被加载的时候会去读config的值,在编辑场景中时候如果生成一个recast实例,在属性面板中覆盖了这个值,就会被保存到关卡中,无论怎么修改config值都不会影响已经保存的这个实例已经覆盖的值,除非你把这个实例删除了,下次启动编辑器又拖出一个实例,这个实例的默认值就会受config影响,希望这样解释对您有所帮助😁

2.我看了下,看上去为了动态导航构建tile的效率稍微牺牲了一点质量,选择了ChunkyMonotone

RegionPartitioning=ChunkyMonotone
LayerPartitioning=Monotone

其他的参数都是默认的

1.明白了,非常感谢。

2.您说其他的都是默认值,Cell Size那些也没有改动么?那么在FN中默认是用的哪个配置呢?(Low, Default,High)

因为这个值是保存在每个地图中的实例里的,场景中有许多尺寸不同的地图,所以并没有统一保存在config里,我这里找了一个示例您可以参考一下

[Image Removed]

好的,非常感谢。我们参考下看看。

另外想请问下,FN中,TileSizeUU的值是怎么设置的? 我印象中,好像推荐是Cell Size的32到128倍? 想看看FN是怎么调整的。

是的,一般来说这个值设置越大导航数据占用内存更少但是动态重建开销更高,越小占用内存变大但是重建开销变低,fn不同地图设置不一样,总体控制在650到1100之间,你们可以结合项目中测试的效率和内存做个平衡