高效寻路许多成群的敌人绕过障碍物


20

我正在努力改善游戏敌人的寻路能力。现在,他们基本上只是通过计算自己与玩家之间的角度并朝该方向移动,不断地朝着玩家的确切位置移动。我也有一个植绒算法,可以防止敌人相互堆叠,因此它们会成组,而不是相互夹住。

但是,既然我已经添加了基于图块的地图,那么我就需要敌人也能够绕过障碍物和墙壁。我最初尝试为“不可行走”的瓷砖添加间隔值,以使植绒算法将墙壁和障碍物视为要远离的对象。我还没有弄清楚这是否可行,因为我的初步测试显示敌人击中了一个看不见的“墙”,那里没有不可行走的瓷砖,但由于某种原因,他们击中了它并开始飞扬。

我想知道如果使用A *计算到达播放器的路径,然后使用植绒算法来防止结块,可能会导致性能负担过重。最初,我的游戏将是基于海浪的射击游戏,但我决定改以热线迈阿密为基础进行游戏,因此我可能会减少敌人的数量,偶尔会成群结队,他们更强大。

这是可行的解决方案吗?我将Java与Slick2D一起用作游戏引擎。还是有解决这些问题的更好的解决方案/算法?


7
正如我在编辑中所描述的,“这太重了”是一个问题要问您的探查器,因为这将取决于您的实现,目标硬件,性能预算以及您的游戏环境–您和探查器都知道的所有内容亲密无间,但互联网陌生人却没有。如果您想有效地引导鸡群寻路,我们可以建议一些策略来帮助您,但是只有您自己的分析才能回答满足您需求的有效方法。如果您分析并确定了特定的性能问题,我们还可以帮助您找到解决该问题的方法。
DMGregory

1
如何实现它们会影响性能。例如,仅在领导者上运行A *并依靠植群吸引追随者。
皮卡列克

如果您的游戏主要是基于与这些敌人的战斗,那么您采用的算法将对游戏的感觉产生重大影响。因此,您应该尝试不同的方法,例如,感觉敌人是否始终清楚地知道玩家的水平和位置,并且像在一个全知的AI的指导下那样跟踪玩家?-其他方法可能是让敌人朝通常的方向奔跑,在该方向上玩家发出声音并且仅朝着视线向他奔跑,或者大喊并告知其他敌人玩家所在的地方...
Falco

@Falco由于游戏不再基于波动,而将基于等级,并且由于敌人是僵尸……我正在考虑制造它,因此您必须被观察或被他们吵醒才能找到您。那么,如果您使用嘈杂的武器?它会在一定范围内发出声音,范围内的所有敌人都会向发出声音的位置移动,然后会随机绕过该区域。
达琳·博德罗

Answers:


49

这听起来像是流场的用例。

在此技术中,您从播放器对象向外进行单个寻路查询,将遇到的每个单元格标记为到达该单元格的单元格。

如果您所有的图块/边缘具有相同的遍历成本,则可以使用简单的广度优先搜索。否则,Dijkstra的算法(如无目标/启发式算法的A *)有效。

这将创建一个流字段:一个查找表,该表将每个单元格与下一步从该位置向最近的玩家对象相关联。

现在,每个敌人都可以在流场中查找其当前位置,以在避开最短障碍物路径的最短路径中找到下一步,而无需各自进行寻路查询。

这样,您的羊群中的敌人越多,规模就越好。对于单个敌人而言,它比A *昂贵,因为它可以搜索整个地图(尽管您可以在到达所有寻路特工时提前撤离)。但是,随着您添加更多敌人,他们将通过一次而不是一遍又一遍地计算共享路径段来分享越来越多的寻路成本。您还可以从BFS / Dijkdtra的结果比A *更简单,并且通常更便宜地评估每个检查的单元格来获得优势。

恰恰是达到收支平衡点的地方,从单个A *便宜到带有备忘录的A *便宜(在这里您将某些结果重新用于过去的寻路查询以加快下一个寻路),是否便宜,将取决于您的实现,代理的数量以及地图的大小。但是,如果您计划在密闭区域中从多个方向接近的一大群敌人,那么一个流场几乎肯定会比迭代A *便宜。

举一个极端的例子,您可以在这里看到一个视频,其中包含2万个座席,他们同时在相当小的网格上同时进行寻路


这项技术听起来真的很整洁。我会检查出来的。
Darin Beaudreau 8:22

15
可以使用构造局部流场的混合算法,而不用像重复调用A *那样搜索更多的映射,并且永远不会搜索相同的位置两次。基本思路是选择一个任意敌人,并从玩家朝该敌人开始进行A *搜索,像在正常流场生成中一样,在遇到它们时标记它们。搜索找到该敌人后,请选择另一个敌人(您尚未找到)作为目标,根据新的启发式方法对开放集重新排序,然后继续搜索。找到所有敌人后停下来。
Ilmari Karonen

1
避免碰撞呢?这(在某种程度上)在OP中提到(避免在到达播放器时剪辑)。在我看来,每当有任何移动(或添加一些其他逻辑)时,您都必须重新运行完整的djikstras
Mars

2
@Mars OP谈论植绒,所以我假设所有个人都可以以相同的速度移动。唯一会引起冲突的地方是瓶颈,这需要一些羊群停止并等​​待。但是,它实际上并不需要更改寻路功能-在大多数情况下,简单的队列可能就可以很好地工作,并且某些路径偏差(某些具有类似成本的替代路径的伪随机选择)将可以产生更自然的外观的流量也避免了整个羊群试图穿越一个特定的单块差距:)
六安

3
@Luaan在基于图块的游戏中,您会惊讶于碰撞发生的频率。我个人认为“排队”选项不是最佳选择。另外,如果单位无法通过彼此,则您需要重新计算单位何时开始进入最终位置以及其他边缘情况。植绒很难;)
火星

8

A *性能不高。我将通过改变算法来解决这种情况。时不时地进行A *,并在两次检查之间检查是否可以自由进行下一步或您需要规避。

例如,跟踪玩家到A *目标位置的距离,如果它超过阈值,则重新计算a *,然后进行更新动作。大多数游戏使用航路点的组合,例如,用于路径查找的简化网格和使用光线投射的逃避转向算法处理航路点之间运动的逻辑。在我看来,特工试图通过绕过他们附近的障碍物来跑到遥远的路点是最好的方法。

最好在这里使用有限状态机,并阅读Mat Buckland撰写的“通过示例编程AI”一书。该书为您的问题提供了行之有效的技术,并详细介绍了所需的数学运算。本书的源代码可以在网上找到;本书采用C ++语言编写,但可以提供一些翻译(包括Java)。


2
使用不经常更新的A *方法,可能会错开您的更新,并为允许在单个帧上重新路由多少个敌人制定预算。这样,您可以限制每帧的峰值寻路成本,并通过分摊多个帧的总成本来更强大地处理许多AI路径。当框架的预算已超出预算时,使用一两个框架的陈旧路径的AI,或者如果接近则不进行推算,通常不会造成破坏。
DMGregory

2
大概在这里说清楚了,但是如果您只想更新给定帧中的某些路径,则可能需要基于与播放器距离的优先级系统。更新玩家附近的敌人可能更重要,而更新远处的敌人使用陈旧的路径可能还可以。
AC

4

不仅可行,而且我相信它是在90年代的商业游戏-BattleZone(1998)中完成的。

该游戏具有3D单位,这些单位具有免费的非基于图块的移动和基于图块的基础构造。

看起来是这样的:

首先,是A *或类似的东西(可能是A *的变体,对它可以找到的路径有严格的限制,因此它永远不会花费太多的资源来运行,但不一定总能找到到达目的地的路径)将用于为气垫坦克找到到达目的地的路径而不会陷入基于瓷砖的障碍中。

然后,坦克会飞来飞去,直到被吸引到其路径中附近瓷砖的中心,并被障碍物,其他附近的坦克等击退为止。


1
那么,处理路径的好方法是什么呢?如果我允许小孩子转弯,我必须能够阻止敌人撞到障碍物的拐角处。我是否应该同时保持敌人和障碍物的植绒行为并添加A *来应对这些情况?
达琳·博德罗
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.