最新版本已支持UE5,详见github的UE5.0分支:ue4-export-nav-data/tree/UE5.0。
Recast Navigation是一个开源的游戏导航/寻路引擎,可以为游戏中的AI提供寻路计算。UE和Unity都是集成了RecastNavigation来为游戏提供导航和寻路计算(当然是修改过的版本),UE的模块NavigationSystem
以及NavMesh
中可以看到相关的代码实现。
最近有个需求是要将客户端的地图信息导出给非UE网络架构的服务端,用于在服务器上对玩家位置的校验,想到可以把客户端的生成的导航数据导出作为客户端世界的地图,所以折腾了一下写了一个UE的插件(开源在Github上:**ue4-export-nav-data)实现了直接**将UE生成的导航数据导出,有兴趣的可以直接去看具体的代码。
根据导出的导航数据可以完整地在非UE网络架构的服务端上实现基于Recast Navigation的寻路计算,而且与UE无缝衔接。
**2019.12.04 Update:**本插件已上架虚幻商城,购买链接ExportNavigation,为了程序员情怀支持开源,所以该项目在Github上的开源仓库不会关闭,但基本不会更新,如果该插件对你有用,欢迎在商城购买支持作者。
Recast Navigation
首先,先来简单介绍一下编译Recast的github开源版本,UE引擎中使用的recast就是基于该开源版本修改的,截止到UE_4.22.3
,UE使用的recast版本为v1.4
(可以从Source/Runtime/Navmesh/Recast-Readme.txt
中查看不同引擎版本使用的recast版本信息)。
RecastNavigation在Github上的源码地址:recastnavigation.
recastnavigation的代码中提供了导航网格生成与计算寻路的工具RecastDemo
,可以作为在项目中集成RecastNavigation的案例。
README.md
里面写了各个平台的编译流程,我在这里详细展开一下Windows下编译流程。
- 首先下载premake5,并将其添加到系统PATH路径
- clone RecastNavigation的代码
- 下载SDL2(选择Development Libraries),并将其解压到
recastnavigation\RecastDemo\Contrib
目录下,将文件夹改名为SDL
,目录结构为:
1 | D:\recastnavigation\RecastDemo\Contrib\SDL>tree /a |
在
recastnavigation\RecastDemo
目录下执行命令premake5 vs2017
(vs201x取决于你当前系统中安装的版本),它会在RecastDemo
目录下创建build/vs2017
目录,里面是VS项目的解决方案。
打开
RecastDemo\Build\vs2017\recastnavigation.sln
,编译即可。编译出来
RecastDemo.exe
位置在RecastDemo\Bin
。
1 | C:\Users\imzlp\source\repos\recastnavigation\RecastDemo\Bin>tree /a /f |
其中关键的几个文件:DroidSans.ttf
/RecastDemo.exe
/SDL2.dll
/Meshs/
。
注意:必须把obj文件放到
Meshs/
目录下才可以被RecastDemo
识别。
之后就可以打开RecastDemo.exe
在默认提供的三个obj
的模型上进行导航数据生成的测试了,通过Build
生成,然后Save保存会在RecastDemo.exe
所在的目录产生一个.bin
文件,即使用recast生成的导航数据。
注意:从UE导出Navmesh的含义是,把UE寻路范围内的模型导出,再通过RecastDemo
在该模型的基础上生成寻路数据。这也导致了在UE中添加影响寻路的框,导出Navmesh在RecastDemo
生成时无法生效。
Plugin: ue-export-nav-data
该插件是从UE中导出RecastNavigation的工具,分为两个模块:ExportNavRuntime
与ExportNavEditor
,编辑器模块提供了UE中编辑器ToolBar
的按钮,在编辑器中导出导航数据。
点击之后选择路径,会在选择的路径下生成两个文件:.bin
与obj
,在Windows下会自动在资源管理器中打开导出目录。
- bin:UE构建完成的导航数据,给外部服务器使用。
- obj:UE中放置寻路的Mesh,可以从RecastDemo中生成bin文件。
另外,我提供了NavData
可以在运行时导出,但是NavMesh
不支持,因为UE的导航是预计算的,具体可以看UFlibExportNavData
中提供的方法。
我在C++和蓝图中也提供了从导出的bin中验证位置是否是合法的寻路位置的两种方法:
1 | bool UFlibExportNavData::IsValidNavigationPointInNavbin(const FString& InNavBinPath, const FVector& Point, const FVector InExtern = FVector::ZeroVector); |
可以与UE中提供的UNavigationSystemV1::ProjectPointToNavigation
来对比验证导出数据是否匹配。
还有一个传入起始点来获取导航路径点的方法:
1 | bool FindDetourPathByNavMesh(dtNavMesh* InNavMesh ,const FVector3& InStart, const FVector3& InEnd, std::vector<FVector3>& OutPaths); |
可以与引擎中UNavigationSystemV1::FindPathToLocationSynchrously
的结果一致,传入游戏中的世界坐标,函数内部有转换,返回的也是世界坐标。
该插件其优点为:
- 并非先从UE导出NavMesh的
.obj
再使用RecastDemo
生成,而是直接从UE导出bin
,当然我也保留了导出NavMesh为obj
; - 因为是直接从UE生成之后的导航数据导出,所以是所见即所得,解决导出NavMesh再RecastDemo生成导航网格时无法避免某些区域不生成寻路,以及避免UE与RecastDemo各种寻路参数的不一致产生的寻路数据不一致;
- 额外抽取出ue的ue-detour版本,可以无缝集成到外部服务器中,客户端坐标与服务端坐标无需转换(当然UE的坐标与Recast的坐标需要转换,但是内部已经处理,使用时不需要手动转换)。
UE的坐标系与Recast的坐标系之间的转换可以使用UE4RecastHelper
的两个函数:
1 | namespace UE4RecastHelper |
Library: ue-recast-detour
这个是我从UE代码中抽取出的recast detour库,在UE源码的路径下为Runtime/Navmesh/Detour
,主要目的是保证UE客户端与外部服务器的验证方法一致。
因为在github上的RecastNavigation要高于UE使用的版本,而且前面提到UE在recast的基础上做了不少改动,为了防止代码的差异造成的不同结果,我将ue使用(以及魔改)过的版本抽出来供外部使用,这样可以确保客户端和服务端的结果是一致的。
代码放在了github:ue4-recast-detour,该仓库的Detour/
目录下为Detour的库的全部代码。
其余的代码是我实现的与UE进行验证和UE与Recast坐标转换的库UE4RecastHelper
类以及实现的一个简单的命令行程序,用来测试UE中的世界位置是否在bin中的寻路数据中合法。
UE4RecastHelper
目前(2019.11.01)提供了dtNavMesh
与bin
文件之间serialize
/deserialize
的方法;以及与UE中函数UNavigationSystemV1::ProjectPointToNavigation
实现方法相同的函数UE4RecastHelper::dtIsValidNavigationPoint
,用来验证点是否是合法的寻路点,保证了UE客户端与外部服务器的验证方法一致。
Detour
所支持的操作都可以在服务器上实现(因为已经从UE里拿到了导航数据),可以根据需求扩展。
再简单说一下ue-detour.exe
这个工具怎么用,直接在命令行启动ue4-detour.exe
会提示用法。
首先,要先从UE中将导航数据导出,这里需要用到的只有.bin
文件,如生成在D:\NavData
。
然后找到ue4-detour.exe
就可以使用下列命令了:
1 | D:\>ue4-detour.exe |
在蓝图中也可以直接加载.bin
进行测试:
End
本篇文章用到的开源仓库:
Update
2021.05.27 Update:
- 插件支持UE5,支持导出UE5的NavMesh数据及导航网格
- 数据与ue-detour验证成功