【问题标题】:How to improve the perfomance of my A* path finder?如何提高我的 A* 路径查找器的性能?
【发布时间】:2013-02-27 14:46:40
【问题描述】:

所以基本上我编写了一个 A* 探路者,它可以找到穿过障碍物的路径并进行诊断。我基本上将http://www.policyalmanac.org/games/aStarTutorial.htm的伪代码实现为真实代码,并使用二进制堆方法从openlist中添加和删除项目。

使用二叉堆带来了显着的性能提升,比我之前使用的插入排序算法快了大约 500 倍。

问题是它仍然平均需要大约 150 万纳秒,大约是 0.0015 秒。

所以问题是,我的计划是制作一款塔防游戏,每次我在地图上添加一座塔时,每个暴徒的寻路都需要更新。如果我在地图上最多有大约 50 个小怪,这意味着更新整个小怪的所有路径大约需要 0.0015 * 50 = 0.075 秒。游戏基本上每 1/60 秒(即 0.016 秒)打勾(所有游戏内容更新),所以问题是更新路径的时间比打勾的时间长,这将导致巨大的延迟。那么我该怎么做呢?我是否需要找到一个更好的算法来对 openlist 进行排序,或者以某种方式划分寻路任务,以便每个刻度只执行 X 个寻路任务,而不是全部。

【问题讨论】:

  • 你的问题对于你给我们的描述来说太具体了。

标签: java artificial-intelligence a-star


【解决方案1】:

不是从每个敌人搜索到检查站,而是一次从检查站向外搜索到每个敌人。这样,您只需进行一次搜索,而不是进行 50 次搜索。

更具体地说,只需从玩家向外进行广度优先搜索(或djikstra's,如果您的图表是加权的),直到找到所有敌人。

您可以通过将启发式 EstimatedDistanceToEnd(又名 h(x)) 更改为对任何敌人的最小估计来更改此策略以使用 A*,但是对于很多敌人,这可能最终比更简单的选项慢。启发式必须是 consistent 才能工作。


此外,请确保您使用的是correct tie-breaking criteria。

另外,最重要的是,请记住,对于大多数游戏来说,您不需要在每一帧都运行探路者 - 通常每秒只运行一到两次,甚至更少,取决于游戏。

如果这仍然太慢,您可以考虑使用D* lite 在后续搜索之间重用信息。但是,我敢打赌,运行单一的广度优先搜索将绰绰有余。

(复制自我在 gamedev 上对 a similar question 的回答)

【讨论】:

  • Djisktra 或广度优先是否比 A* 探路者快?我仍然不太明白您对 EstimatedDistanceToEnd 的解释,但如果它们能显着提升性能,我很想先尝试 djistra/breadth。我还阅读了您提供的文章,但它没有涉及如何使用它来导航到多个目标(在我的情况下是敌人)的路径。我还用谷歌搜索了这两种算法,但没有找到任何可以用来编写代码的菜鸟友好文章。你知道像policyalmanac.org/games/aStarTutorial.htm这样的文章吗
  • 广度优先搜索也会给我最短路径吗?我读了这篇文章,它似乎比 A* 简单得多。我只是不知道它是否会给我最短的路径。请回复
  • 谢谢,我想我首先了解 DJikstra/ 广度。告诉我我是否错了,但 Djikstra 基本上听起来像一个更简单的 A*,而无需计算启发式/开放列表排序,而且由于我有不同的移动成本——(N、W、S、E)移动将花费 10 ,而 NW、NE、SE、SW 移动将花费 14 - 我猜我会使用 djikstra,而不是首先使用广度。
  • 最后,听起来 djikstra 会有更好的性能,因为它会做更少的计算,并且摆脱了我需要为重新分配每个敌人的路径而编写的所有不必要的额外代码,如果我将使用 A*。所以我想我的问题是,我们什么时候使用 A* 而不是 djikstra?我花了所有时间学习/编写带有二进制堆的 A* 代码,结果却发现我的塔防游戏不需要它。像星际争霸这样对 100 多个实体使用 A* 的游戏表现如何?他们是否使用某种特殊的 A* 算法?
  • @GayLord:过于简单化:BFS 是“显而易见的”算法; Dijkstra 是 BFS 的扩展,适用于加权图; A* 是 Dijkstra 的扩展,当EstimatedDistance 启发式可用时加速算法(将启发式设置为0 完全等同于 Dijkstra 的算法)。星际争霸之类的游戏可能会按照我上面的解释进行。
【解决方案2】:

您是否考虑过 Floyd-Warshall 算法?

本质上,A* 用于从单个源到一个或多个目的地的路径查找。然而,在塔防中(当然取决于你的规则),它是关于在地图上导航的多个来源。

因此,对于这一点,弗洛伊德的算法似乎更优化。但是,您可以让 A* 算法找到单元组而不是单个单元的路径,这样可以优化您的计算时间。

【讨论】:

  • -1 Floyd-Warshall 用于查找所有对的最短路径。对于塔防游戏来说,这将是非常低效的。看我的回答。
  • 所以我是最初提出这个问题的人。我现在的目标是制作一款类似于桌面塔防的游戏。您可以在地图上添加/删除塔,敌人会相应地改变他们的路径。显然,我相信使用 A* 这样做会非常慢,因为我计划在地图上至少有 50 个实体,并且每次玩家添加/删除塔时让每个实体重新计算其路径将需要很长时间。那么我应该使用什么算法呢?到目前为止,人们已经推荐了 quadtree、d lite、djikstra、jump point search,但在这些方面真的找不到任何对新手友好的 tut
  • @BlueRaja-DannyPflughoeft 您可以为塔防应用程序定制它。本质上,每当一个节点发生变化时,它都会从周围的瓦片中重新计算该节点的成本,并且对于每个周围的瓦片,如果它发生了变化,就会在它们上调用算法。所以不需要“游戏范围”的重新计算。 A* 不会是最优的,因为通常来源的数量超过板上的瓷砖数量,并且每次“某事”发生变化时,您都需要重新启动算法......
  • @GayLord:D*-lite 和 JPS 太过分了;和四叉树无关。 Floyd-Warshall 是对错误问题的正确答案。只需使用广度优先搜索,使用检查点作为开始,并在到达所有单位时结束,如我的回答中所建议的那样。理解和实现起来非常简单 - 参见例如 here
  • 我已经在使用类似的东西了。我需要的是一种在地图上放置或删除新塔时动态更改路径的方法,而无需计算每个敌人的路径
【解决方案3】:

据推测,您可以从出口向后搜索所有小兵,因此您只需要探索一次迷宫。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 2021-07-30
    相关资源
    最近更新 更多