Export Recast Navigation Data from UE4

最新版本已支持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下编译流程。

  1. 首先下载premake5,并将其添加到系统PATH路径
  2. clone RecastNavigation的代码
  3. 下载SDL2(选择Development Libraries),并将其解压到recastnavigation\RecastDemo\Contrib目录下,将文件夹改名为SDL,目录结构为:
1
2
3
4
5
6
D:\recastnavigation\RecastDemo\Contrib\SDL>tree /a
+---docs
+---include
\---lib
+---x64
\---x86
  1. recastnavigation\RecastDemo目录下执行命令premake5 vs2017(vs201x取决于你当前系统中安装的版本),它会在RecastDemo目录下创建build/vs2017目录,里面是VS项目的解决方案。

  2. 打开RecastDemo\Build\vs2017\recastnavigation.sln,编译即可。

  3. 编译出来RecastDemo.exe位置在RecastDemo\Bin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
C:\Users\imzlp\source\repos\recastnavigation\RecastDemo\Bin>tree /a /f
文件夹 PATH 列表
卷序列号为 000002D0 ECDB:6872
C:.
| .gitignore
| DroidSans.ttf
| RecastDemo.exe
| RecastDemo.pdb
| SDL2.dll
| Tests.exe
| Tests.pdb
|
+---Meshes
| dungeon.obj
| nav_test.obj
| undulating.obj
|
\---TestCases
movement_test.txt
nav_mesh_test.txt
raycast_test.txt

其中关键的几个文件: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的工具,分为两个模块:ExportNavRuntimeExportNavEditor,编辑器模块提供了UE中编辑器ToolBar的按钮,在编辑器中导出导航数据。

点击之后选择路径,会在选择的路径下生成两个文件:.binobj,在Windows下会自动在资源管理器中打开导出目录。

  • bin:UE构建完成的导航数据,给外部服务器使用。
  • obj:UE中放置寻路的Mesh,可以从RecastDemo中生成bin文件。


另外,我提供了NavData可以在运行时导出,但是NavMesh不支持,因为UE的导航是预计算的,具体可以看UFlibExportNavData中提供的方法。

我在C++和蓝图中也提供了从导出的bin中验证位置是否是合法的寻路位置的两种方法:

1
2
bool UFlibExportNavData::IsValidNavigationPointInNavbin(const FString& InNavBinPath, const FVector& Point, const FVector InExtern = FVector::ZeroVector);
bool UFlibExportNavData::IsValidNavigationPointInNavObj(class UdtNavMeshWrapper* InDtNavObject ,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
2
3
4
5
6
7
8
9
10
11
12
namespace UE4RecastHelper
{
FCustomVector Recast2UnrealPoint(const FCustomVector& Vector)
{
return FCustomVector(-Vector.X, -Vector.Z, Vector.Y);
}

FCustomVector Unreal2RecastPoint(const FCustomVector& Vector)
{
return FCustomVector(-Vector.X, Vector.Z, -Vector.Y);
}
};

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)提供了dtNavMeshbin文件之间serialize/deserialize的方法;以及与UE中函数UNavigationSystemV1::ProjectPointToNavigation实现方法相同的函数UE4RecastHelper::dtIsValidNavigationPoint,用来验证点是否是合法的寻路点,保证了UE客户端与外部服务器的验证方法一致。

Detour所支持的操作都可以在服务器上实现(因为已经从UE里拿到了导航数据),可以根据需求扩展。

再简单说一下ue-detour.exe这个工具怎么用,直接在命令行启动ue4-detour.exe会提示用法。
首先,要先从UE中将导航数据导出,这里需要用到的只有.bin文件,如生成在D:\NavData
然后找到ue4-detour.exe就可以使用下列命令了:

1
2
3
4
5
6
D:\>ue4-detour.exe
Usage:
ue4-detour.exe dtNavMesh.bin Loc.X Loc.Y,loc.Z Extren.X Extern.Y Extren.Z
PS:{Extern.X Extern.Y Extern.Z} can be ignored,default is {10.f 10.f 10.f}
For Example:
ue4-detour.exe dtNavMesh.bin -770.003 -593.709 130.267 10.0 10.0 10.0


在蓝图中也可以直接加载.bin进行测试:

End

本篇文章用到的开源仓库:

Update

2021.05.27 Update

  • 插件支持UE5,支持导出UE5的NavMesh数据及导航网格
  • 数据与ue-detour验证成功


全文完,若有不足之处请评论指正。

微信扫描二维码,关注我的公众号。

本文标题:Export Recast Navigation Data from UE4
文章作者:查利鹏
发布时间:2019年11月01日 09时18分
本文字数:本文一共有3.4k字
原始链接:https://imzlp.com/posts/20203/
许可协议: CC BY-NC-SA 4.0
文章禁止全文转载,摘要转发请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!