导航数据的构建流程
导航数据的收集
导航系统中绑定了Actor、Component注册完成以及取消时的委托,通过这些委托把数据及时更新到导航系统的八叉树结构中
导航系统的辅助结构DefaultOctreeController、DefaultDirtyAreasController分别承担了空间数据查询和置脏区域重新构建的任务,后者会把置脏数据最终投递到导航数据生成器的待处理结构里最终执行生成操作
开启构建操作(静态构建)
开启导航数据构建有几种情况:开启了动态导航、指令集开启、编辑器模式下的自动构建开启、调整导航偏移导航失效造成的重新构建。构建执行流程大致如下:
当开启导航构建后导航系统首先重置掉待处理区域变更请求以及控制置脏数据的管理器,然后迭代所有的ARecastNavMesh执行同名构建函数RebuildAll
ARecastNavMesh首先会检查是否有正在构建操作如果存在操作则取消并重置,构建新的导航数据生成器实例并执行初始化,在初始化中进行有效区域边界更新并置脏所有的边界
把边界数据投递到待处理结构中,然后通过执行构建生成器的EnsureBuildCompletion函数确认所有的构建工作完成,实质上是把所有的待处理结构打包成异步或者同步执行的任务来处理
其中值得提及的是收集碰撞数据的方法:导航系统的辅助结构DefaultOctreeController中的NavOctree与DirtyBound做交叉检测,符合的则做数据收集
使用瓦片生成器结构构建瓦片数据
瓦片导航数据生成完成以后会把生成的数据添加到ARecastNavMesh数据真正的持有者DetourNavMesh(dtNavMesh)中
动态导航数据与静态生成区别:动态导航模式下导航系统中挂载的Actor、Component注册取消委托受场景变更的影响会不断的更新,进而推动整个构建导航逻辑的执行(而且在动态模式下这些具有碰撞数据的实例会及时导出碰撞数据)。
生成瓦片数据的逻辑
当FRecastTileGeneratorTask异步执行或者同步执行一个构建的任务时FRecastTileGenerator::DoWork的调用就开始了,FRecastTileGenerator结构封装了生成单个瓦片的功能逻辑(封装Recast导航数据生成流程),DoWork的执行流程如下:
完成几何模型碰撞数据收集和缓存,其中包括顶点数据、索引数据、可行走斜坡结构数据、修改器、导航连接、瓦片原生几何数据等
构建高度场域数据(rcHeightfield)
计算光栅化遮罩(对导航Modifier进行处理)
光栅化或者说体素化三角形面(其中包括几何Transform数据从UE坐标到Recast的坐标转换)
标记可行走区域
体素边界过滤,防止边界外生成体素数据,通过InclusionBounds边界框判定(ApplyVoxelFilter)
Recast的生成过滤(WalkableClimb、walkableHeight)
生成紧缩高度场域(CompactHeightField)
根据walkableRadius剔除边缘(rcErodeWalkableAndLowAreas)
根据选择的算法生成区域数据(rcBuildDistanceField)
生成导航数据保存到瓦片生成器中
回收脚手架结构内存
导航数据的查询
导航系统封装的查询接口
K2_ProjectPointToNavigation 根据传入的点获取在NavMesh上的投影位置
K2_GetRandomReachablePointInRadius 获取指定半径内随机的一个导航可达点位
K2_GetRandomLocationInNavigableRadius 在给定的原点半径内的导航空间中生成一个随机位置
GetPathCost 获取路径消耗,不推荐使用