上周的工作重点转移到服务器寻路上来,刚刚做完没几天,总结一下,当时团队讨论的结果是使用 Unity 原生的 NavMesh 系统,然后将数据导出到服务器使用。我最初的思路是将导出的网格加载到服务器后,自己写 A* 算法来寻路,但看了 RecastNavigation 后,果断放弃想法,想使用已导出的数据到 RecastNavigation 中使用,按照作者的简介是可以,但是并没有相关的代码,后来翻到了一篇关于这个的帖子,作者明确回答说没有时间做这个功能,所以就只能自己动手,丰衣足食了,有这么个系统已经很棒了。
第一步工作就是分析 RecastNavigation 的工作流,我后来着重分析了 rcPolyMesh 的结构,计划并利用通过普通 Mesh 生成 rcPolyMesh,然后再生成 dtNavMesh 的过程,只要 dtNavMesh 生成就可以保存真正的导航数据了。
第二部就开始尝试将任意的 Mesh 转换成 rcPolyMesh,这一步最主要的过程是生成相应的多边形以及它们的邻边,你可以把所有的多边形都用 Mesh 的三角形替代,但是可能导致最终的 NavMesh 并不是最优化的,并且通过试验发现,三角形过多,多边形过细,反而出现了寻路不精确的情况,不知道是否是我的数据有问题,我的方法是先用上述方法把每个多边形设置为基础的三角形,然后用内建的函数来优化合并多边形,接着再建立邻边即可,这样就可以得出最优化的 NavMesh 最终数据。
第三部仅限于使用 Unity 导出的 NavMesh 的情况,这里发现了很有意思的问题,Unity 在导出 NavMesh 的接口里做了一点小小的 Smart Trick,这里面的 Mesh 数据是包含 NavMesh 中得多边形 Poly 信息的!是的,你没有看错!我也是走了弯路才发现这个,因为当你直接用第二部的方法将 Unity 导出的 NavMesh 到 RecastNavigation 中,发现整个 Mesh 的内部出现了好多的 Outer Border,这说明这些边和其它多边形没有公共边,可是明明肉眼是能看到非常确定他们是共享某条被标记为 Outer Border 的边的,查了多遍建立邻边算法(一开始是自己写的)确实没有问题,后来猜测唯一的原因应该是出现了重复顶点-多个顶点具有相同的位置,将其原始数据导入到 Max 中发现果然如此!将数据导出成 obj,打开文件也发现了相同顶点数值。既然这样,你当然可以利用这些信息来建立多边形,这样多边形信息和 Unity 中会一模一样,是最完美的结果,很可惜迫于时间的压力我暂时没想到合适的分析算法,选择了第二种方案:在进行第二步之前,先将 Unity 导出的 NavMesh 中相同数值的顶点进行合并,然后再优化合并多边形,建立邻边,这样可能最终的多边形未必和 Unity 中一样,但是并不影响寻路,而且也足够优化,是目前性价比最高的方案。
目前局限:不支持 DetailMesh(上述情况 DetailMesh 和 NavMesh 是相同的),不支持 OffMeshLink,但目前够我们的项目使用了,而且效果也非常理想。感兴趣的朋友可以按照上述方法尝试。
另外:RecastNavigation 有非常好的 Demo 和代码注释,但是几乎没有什么文档来讲解整个 Pileline 后面的原理,但找到了个 CritterAI 系统,一个基于 RecastNavigation 系统,用 C# 实现的 AI 寻路系统,有着非常详细的文档,对理解 RecastNavigation 有很大的帮助。我自己也在学习整个系统,还有很多地方还不理解有待挖掘。
文档地址:
http://critterai.org/projects/cainav/doc/
关于理解 NavMesh 生成:
http://critterai.org/projects/cainav/doc/html/6fb3041b-e9be-4f03-868b-dcac944df19b.htm
http://critterai.org/projects/cainav/doc/html/e72bd1ee-04b0-4bbb-a21d-d8d7ecaa11af.htm
http://critterai.org/projects/cainav/doc/html/21046960-3dc1-4369-a092-5f5bba4f752c.htm
关于 PolyMesh 的理解,尤其是其有关多边形信息的格式,对于理解 rcPolyMesh 非常关键:
http://www.critterai.org/projects/cainav/doc/html/DE9679E3.htm
http://www.critterai.org/projects/cainav/doc/html/B8C2F0F4.htm
一则关于 Mesh 导入转换成 NavMesh 的讨论帖子:
https://groups.google.com/forum/#!topic/critterai/WY1mj9mz5AE
一则关于作者说不添加导入普通 Mesh 到 NavMesh 功能的讨论贴子:
https://groups.google.com/forum/#!searchin/recastnavigation/import/recastnavigation/PJbyOPUtcaU/KoyGUkExkl8J
这几天又开始转移到客户端,做其它的功能了,大家还得继续加油。