astar pathfinding 缝隙阻挡方案

我们上一个项目是RTS项目,刚开始寻路问题解决方案过程遇到过跟你相似的疑惑,修改探索和调教了很长时间,分享几点仅供参考下吧。

先上结论:采用了两层结构 A Start Pathfinding Project Pro + Unity NavMesh。
1.主体寻路方案使用 A Start Pathfinding Project Pro 这个插件中传统的网格形式,并进行了深度修改扩展,主要是满足寻路过程的通路性需要考虑到单位半径大小,这样寻路精度高;
2.使用 Unity NavMesh 系统作为寻路过程中的碰撞系统,因为你说的很对,这个寻路插件的碰撞有问题,稍后解释。
以上两部分组成“寻路算法+精确碰撞”。

说下以上方案的原因和细节。
1.1 NavMesh 寻路速度快但不够精确,rts还是适合使用传统的四方形 NavGrid 格子寻路,而且现有的任何寻路算法默认都是不支持考虑寻路单位半径大小对寻路过程的影响,但我们策划绝不允许1米宽的缝隙被一个两米宽的胖子挤过去,如果使用 navmesh 并且动态生成阻挡会出现寻路路径是有了,可是由于碰撞问题大的单位会卡在缝隙这里来回“发抖”;这个只能自己动手修改,所以我们买了该插件然后自己从里到外修改,具体修改算法原理和修改后的示意图,你可以参考这里:http://www.cnblogs.com/yaukey/p/rts_unit_traverse_size_based_path_finding.html。 修改完后,每次寻路会将单位的直径大小当做寻路参数之一传入进行寻路。

1.2 使用这个插件开启两个线程左右来寻路是我后来调教后一个比较理想的结果,然后是地图中各种单位会出生和死亡,当单位站定不动,需要生成阻挡;移动了需要移除阻挡恢复此处的通路性,通过再修改下插件中的 DynamicObscule 这个组件(原生功能太简单)来实现;我们具体是,每个单位都有一个对应的大小的 CapsuleCollider 空对象挂上这个脚本,单位站定将该物体放置到单位的位置并激活它,单位移动隐藏该空物体即可,这个脚本会引起地图通路性的更新,这个更新是多线程的,这一点是要注意的,通过回调事件来做响应的事情,切记不要在同一帧或者下一帧去做,不能保证。这样就能让整个地图一直根据单位来更新通路性。

2.寻路的通路性问题解决了,现在来解决碰撞问题,这个插件自带了碰撞算法,使用的 rvo 算法,但是据我当初各种调教实验,它的碰撞都达不到我们的要求,单位多了拥挤的时候,总是会有些单位站立后变得重叠了,最不能接受的是两个单位完全重叠。在这里我花了相当多的时间都不能调教修改的满意。后来想起来 recastnavigation 作者亲口说过虽然 Unity 的 NavMesh 基于此,但是 Detour 系统经过深度的改写,Detour 包含了巡航和碰撞,而实际使用也发现 NavMeshAgent 之间的碰撞是很精确的,于是我想了个取巧的办法,给地表再铺一层跟AStar 插件的寻路面积一样大的 NavMesh,但是没有任何的阻挡(理解为一片纯蓝色),同时给寻路单位添加一个 NavMeshAgent,然而这个东西只用它的碰撞,而不使用寻路(没有阻挡,任何寻路都是两点直线,可以考虑几乎无开销),这样最后实际的碰撞效果才算达到我们满意的效果。

以上就是我所说的两层含义,我再说下坑和问题。

1.当初开发Unity版本是5.3.7-5.3.8,插件版本5.x,寻路插件中底层会有 Physics.CheckCapsule调用,但是多线程大量调用,会导致底层 PhysX 物理引擎崩溃,游戏闪退,不必现但是大量的话很容易一下就挂,插件官方论坛也有这个 bug 讨论,后来我将此换成了两个 Physics.CheckSphere 调用,目前 2017版本没有测试过;

2.我在1.2中使用的方法,在 uwa 测试中每次都是 Dynamic Collider 超标,这个需要自己取舍了,但是总体我们游戏的瓶颈不在寻路一块,消耗在这些测试中看来比较理想;

3.插件中由于是多线程更新,有很多的完成事件回调,基本都是利用这些链接游戏系统中,不够了自己加,否则依然是容易在未更新完成时得到错误的结果;

4.有可能的话再优化下内部的一些堆内存分配,并且和游戏系统结合后注意释放和断开引用,否则容易内存泄漏,造成寻路插件被引用以至于后面引用很长一串对象都不得释放。

5.寻路精度和碰撞精度在游戏中的表现,需要花比较多的时间去调教参数,有时候表现不好未必是方案不好,然后如果你们对实时同步性要求较高,这个方案还必须再进一步完善和扩展下。

我们使用这个寻路方案的项目是:《战地指挥官》,你可以下载看看寻路是否符合你的要求,苹果安卓各平台都有:)

以上是我暂时想起来的一些心得,希望对你有帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值