移动平台上100个人复杂障碍物寻路的思考和实现(理论篇)

【转载】移动平台上100个人复杂障碍物寻路的思考和实现(理论篇)

ps:以下数据均以红米1手机为例。 
  
        去年我做了一个项目,当时就为了十个人寻路的良好体验做了多方尝试,并最终通过改写A*算法,而且写了一篇文章:http://blog.csdn.net/yxriyin/article/details/40902063 
当时能够做到良好的20人以下的多人寻路,在红米上每一帧也只消耗5ms不到的时间。 
        但最近的一个项目是100人左右的在复杂的障碍物之间进行寻路,以前的方法在红米手机上每一帧消耗超过100ms,这是无法接受的。 
        如果条件允许,我倒是想使用自带的寻路系统,自带的寻路用的是navmesh,本质上是节点寻路,效率比A*高1-2个数量级,但遗憾的是,游戏的逻辑让我必须使用A*才能实现对应的功能。 
         
A*是以单元格子作为基本单位的,格子数越多,需要寻路时间越长,我们可以这么来衡量一次A*寻路的性能,此次寻路总共找了200个格子。以coc为例, 
他们的格子大概是100*100,也就是10000个。这个概念可以用红米测试的时间来说明:假设一次寻路总共找了10000个格子,那么标准A*的耗时 
是200ms左右(这里是我自己拿了一个A*插件在手机上的测试),而一个流畅的游戏一帧不会超过30ms。 
       为了达到流畅的水平,那么每一帧只能寻找500个格子左右,大概耗时10ms,(100个人同时渲染已经占领了绝大多数的帧时间,即使实现这个目标,红米上也只能在20帧左右徘徊,不过渲染的优化还有其他手段,我们这里只考虑寻路优化先)。 
       
第一个有效手段是排队,我们认为寻路的ai有一秒延迟是合理的。也就是说,一个单位在原地思考1s以内不动,是一个合理行为。那么假设我们维持在24帧, 
那么就是1s内可以有24个单位排队寻路,每一个人能够尝试找500个格子。但是我们的目标是100个人,也就是说应该是每一帧要有5个人寻路,每一个人 
找100个格子就能找到终点,这样就能实现目标。然而可想而知,在10000个格子内,用A*算法,想要用100个格子就找到目标,除非是毫无障碍物的情 
况。 
      于是我不得不开始思考为何需要消耗如此的点才能找到终点,再看了大量的文章和以下图片后: 

      




我得出一个结论,就是A*在有障碍物的情况下,实在是搜索了太多的无效的点了。而尝试了大半个月的方案后,有一天我突然灵光一闪:我们走迷宫的时 
候,有一个策略,就是贴着墙壁一直往右走,那么假设我修改A*找格子的策略,不再以启发函数主导,而是饶墙主导,启发函数辅助的形式,是不是是就会得出一 
个一直往前冲,碰到墙后绕,绕过去之后继续往前冲到达终点。假设这个能成立,那么寻找的格子将大大减少,因为你和墙壁之间的那一大片都不用找了。 
当然即使行得通,找到的路径也是很奇怪的,会饶墙而行,不过我以前写过几个路径平滑算法,刚好有一个可以完美处理饶墙而行,让路径变成最短路径。 
然后我就马上开始执行这个方案,一边执行一边想,为啥这么牛逼的idea以前没人想到过呢?然后我就发现了问题所在,这么做会出现一个无法解决的情况,就是死胡同, 
假设你刚好走进了一个只有一个格子长度的死胡同,那么你就再也找不到路了。因为节点已经被Close了(写过A*的人应该知道这个意思)。不过生活就是这样,在我们的项目中是完全可以保证不存在这样的死胡同的。所以我就安安心心去做了。 
最终成功实现。策略如下: 
1.计算周围的四个格子,哪一个离终点最近,得到这个格子后,Open之,下面称它为格子A。 
2.判断格子A是否贴墙,如果贴墙,那么就要Open周围的三个格子,进入步骤3。如果不贴墙,就直接跳过周围的其他三个格子,贪婪的跳转到步骤1. 
3。进入A*正常的流程,用启发函数判断权值等等(具体参考标准A*) 


其实很简单,只是通过1和2将大部分格子给pass了,这样的问题也描述了,就是可能找不到路,但是对于我的项目来说,是不会出现的。 
这里有几个重点说明: 
1.在这种策略下4格子搜索比8格子更快。 
2.用这种方式找的路径,必须用路径平滑算法处理,不然走路会很奇怪。 
3.判断是否贴墙要注意如果你在墙角边缘,你要判断周围8个格子,不然可能会忽略一些正确的路径导致绕远路。 
4.如果障碍物不多,这种算法效率会比A*低。 
5.如果障碍物太多,这种算法和A*效率一样,但是由于要路径平滑,所以也会比A*效率低。 
哈哈,看了4和5,是不是坑爹啊。但大部分情况都是这样做效率高。最终测试性能结果和预期还是有点差距,一帧300个格子,10ms,可以让50个人一秒内从地图的一端经过复杂的障碍物寻路到另一端,这是目前的极限。100个人的话,会有2s的思考延迟。 


目前项目就用这个来处理,体验也马马虎虎,当然如果后续有bug我会再说明。虽然我也很喜欢分享源代码,但这个代码是整合在我们整个项目中,分离出来比较麻烦,所以目前只打算做理论分享,实战分享希望以后有空专门写一个demo。       

更多细节参考以前的文章:http://blog.csdn.net/yxriyin/article/category/6057606 

最近发现一个bug,那就是四个字走斜线会比直线要远,这样在我们的游戏中,斜着的墙壁的消耗就比横着的墙壁要大,导致寻路的结果老是斜着的墙壁优先,目前的方案是调整斜着墙壁的消耗值,让他的权重降低,大致和直的相等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Unity中,如果多个怪物在寻路时被障碍物卡住原地踏步,可以采取以下解决方法: 1. 检测障碍物:在怪物进行寻路时,需要进行障碍物的检测。可以使用Unity提供的碰撞检测机制,将障碍物的碰撞体与怪物的碰撞体进行碰撞检测。当怪物检测到障碍物时,可以触发一个停止寻路的事件。 2. 改变目标点:当怪物无法继续寻路时,可以尝试改变其目标点,使其绕过障碍物进行移动。可以通过在目标点周围进行随机偏移,或者计算出可行的绕路路径,来避开障碍物。 3. 寻找最近的路径:如果怪物被关在一片障碍物中无法到达目标点,可以使用寻路算法(如A*算法),来寻找距离原目标点最近的可行路径。这样,即使怪物无法直接到达目标点,也能够尽量接近目标点进行移动。 4. 团队协作:如果多个怪物同时遇到障碍物,可以引入团队协作机制。当一个怪物检测到障碍物时,其他怪物可以等待或绕过该障碍物。可以使用信号机制或状态机来实现怪物之间的协作行为。 总之,解决多个怪物寻路障碍物卡住的问题,需要检测障碍物、改变目标点、寻找最近的路径和引入团队协作等方法,以确保怪物能够顺利进行移动,并绕过障碍物到达目标点。 ### 回答2: 在Unity中,如果多个怪物在寻路时被障碍物卡住原地踏步,可以采取以下方法解决: 1. 调整碰撞体大小:检查怪物的碰撞体是否适当。如果碰撞体太大,怪物可能会被阻挡在障碍物前面无法通过。可以尝试调整碰撞体的大小,让怪物能够正确地穿过障碍物。 2. 使用导航网格:Unity的导航网格系统可以帮助怪物智能地避开障碍物而不被卡住。在场景中创建一个导航网格,并将其应用于怪物的寻路组件。通过设置导航网格的避障参数和路径规划算法,怪物将能够绕过障碍物移动,避免原地踏步。 3. 调整寻路算法:如果怪物的寻路算法不适合当前场景,可能会导致其被卡住原地。可以尝试使用其他寻路算法,如A*算法,来提高怪物的路径规划能力。不同的算法可能适用于不同的场景,因此需要进行实验和调整。 4. 添加避障逻辑:如果以上方法无法解决问题,可以给怪物添加特定的避障逻辑。如使用射线检测来检测前方是否存在障碍物,若存在则选择其他路径或等待障碍物消失后再继续移动。这样可以避免怪物陷入原地踏步的困境。 总之,解决多个怪物寻路障碍物卡住的问题,需要考虑调整碰撞体大小、使用导航网格、调整寻路算法以及添加避障逻辑等方法,根据具体情况选择合适的解决方案。 ### 回答3: 在Unity中解决多个怪物寻路障碍物卡住原地踏步的问题,可以采取以下方法: 1. 寻路算法改进:如果你使用了Unity自带的导航系统(例如NavMesh),可以优化寻路算法以避免怪物被卡住。例如,你可以调整导航系统的参数,使其更加灵敏地避开障碍物,或者通过增加、减少导航网格上的细节,细化碰撞检测的精度。 2. 利用避免行动重叠:在怪物的脚本中,可以设置一个范围,当怪物检测到周围有其他怪物时,它会避免移动到该区域,从而避免了多个怪物互相阻挡的情况。 3. 引入流体仿真:通过模拟流体的方式,可以实现怪物与障碍物之间的动态交互。例如,当怪物靠近障碍物时,障碍物可以自动移动一定的距离,为怪物腾出路径。这种方法需要使用流体动力学的物理引擎,如Unity中的PhysX。 4. 手动设置路径:如果游戏场景的地不是太复杂,你可以手动设置怪物的路径,使它们避开障碍物。你可以在场景中添加特殊的导航点,当怪物检测到障碍物时,它们可以绕开障碍物,沿着指定的路径移动。 5. 使用AI算法:可以借助机器学习或人工智能的算法,让怪物能够自主学习和适应场景中的障碍物,并找到最佳的路径来避开障碍物。 无论使用哪种方法,都需要在游戏开发过程中进行测试和调试,以确保解决了多个怪物寻路障碍物卡住原地踏步的问题,并提供流畅的游戏体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值