背景
最近在实现一个 3D 的沙盒类游戏,基本的功能就是在一个 3D 平面里,进行建筑物的搭建,可以在场景内添加或者编辑建筑物,然后平面内存在一个人物模型,他可以穿梭行走于建筑物之间。

在实现人物的行走功能的时候,我们很自然地想到取终点和起点两点的坐标,然后连成直线进行行走即可,在没有建筑物的时候这个想法确实很好,可是一旦在地图中出现建筑物之后就会发现:忒喵的人物穿模啦!

至此,寻找避障方案之旅开始了。
使用 Babylon.js 自带的避障功能
由于我们的项目是使用 Babylon.js 框架来进行开发的,因此本着“能不自己写坚决不自己写”的原则,我们的第一个想法就是使用 Babylon.js 自带的避障功能。
介绍
简单介绍一下 Babylon.js 中自带的避障功能,它属于框架的一种拓展功能,需要结合 RecastJS 依赖进行使用。
利用 RecastJS 进行导航网格(Navigation Mesh)的生成。然后再通过 RecastJS 中的 Crowd Agents 模块进行自动的寻路和避障。

可能看到这里的你会有一个疑问,什么是导航网格,这里引用一段我在其他博客中看到的定义和介绍:“导航网格(Navigation Mesh),也俗称行走面,是一种用于在复杂空间中导航寻路、标记哪些地方可行走的多边形网格数据结构。”

一个导航网格是由许多的凸多边形组成的,大白话地讲就是将地图切割成 N 份,每份都是一个凸多边形,我们称一个多边形为一个 Poly。
然后当人物在导航网格中行走时,会判断起点和终点是否在同一个 Poly 中,如果是的话,则直接将起点和终点连成直线,该直线即为人物的行走路线;否则就需要使用相应的寻路算法进行路径的计算,计算出人物需要经过哪些 Poly,再利用这些 Poly 算出具体路径。
应用
在知道 Babylon.js 自带了这么一个功能的时候,当时我的内心是狂喜的,于是乎照着官网示例对着键盘一顿乱按后,刷新页面,新增一个建筑,点击地图,期待着人物模型自动地绕开建筑物,结果:

What happened?
经验告诉我,应该是导航网格没有正常生成导致的,幸好,RecastJS 提供了多样化的参数让我可以去调整导航网格的生成规则。
于是乎,经过了几乎一整天的参数调整,最后发现是我太天真了,结果根本没有发生什么变化。只有当添加的障碍物体积很小很小的时候,人物的避障功能才能成功生效,当障碍物的体积稍微大一点点,人物就会直直地穿过建筑到达终点。
当时我的想法是:行吧,既然调参也没有用,那我去看看 RecastJS 的源码,看看它是如何生成导航网格的,以及是什么导致它导航网格生成不正常的。
所以,我转战到了 github。不搜不知道,一搜吓一跳,发现这个 RecastJS 原来前身是一个 C 语言开发的库,后来不知道被谁转成了 Javascript 版本发到了 npm 上,也就是说,我们看不到

本文介绍了在3D沙盒游戏中实现人物行走避障功能的挑战,重点讨论了使用Babylon.js自带的RecastJS避障功能的局限性,以及自建导航网格和A*搜索算法的过程。通过简化地图和建筑物为导航网格,结合A*算法优化路径,解决了人物穿模问题,最终通过拉绳算法优化路径拐点,实现了理想中的避障效果。
最低0.47元/天 解锁文章
6000

被折叠的 条评论
为什么被折叠?



