【问题标题】:Fast any-angle pathfinding快速任意角度寻路
【发布时间】:2014-07-14 18:49:47
【问题描述】:

我正在为移动设备开发一款游戏,但在决定为​​我的 AI 使用哪种寻路算法时遇到了一些麻烦。我的游戏是在最大为 200x200 的静态网格地图上进行的。玩家可以向任何方向移动。由于游戏是针对移动设备的,所以算法需要非常快并且可以牺牲最优性。

到目前为止,我已经研究了几种算法:

  • 具有 JPS 优化的 A* - 据说速度很快,但会找到离散的网格路径
  • HPA* - 正如我所期望的那样,它可能比 A* + JPS 更快,但不是最优的,并且也能找到离散的路径
  • Theta* - 这个可以找到不错的连续路径,但对于远处的点来说太慢了
  • Anya (http://www.grastien.net/ban/articles/hg-icaps13.pdf) - 最佳和任意角度,但相对未知,我怀疑它会太慢(我没有找到任何基准)

哪种技术最适合我的需求?也许有一些好的和有效的平滑技术可以用来发布 JPS/HPA* 找到的过程路径?还是有一些在连续路径上运行的快速分层算法?

【问题讨论】:

  • static 是否意味着您可以预先计算路径数据或者您的地图不是静态的?
  • 地图永远不会改变,所以预先计算绝对是一种选择。
  • 我真的没有任何进一步的建议。 :) 好吧,这是一个谎言,如何将您的地图划分为“视线可达”区域的图形?在区域内你可以直接走路线,区域之间的移动可以通过更小的连接图来完成。

标签: performance algorithm path-finding a-star


【解决方案1】:

如 cmets 中所述,在开始任何更复杂的事情之前,首先应尝试使用标准启发式搜索算法进行适当的预计算、导航网格(或概率路线图)和其他状态空间缩减。

但是,即使您的网格每帧都在变化,200 x 200 的网格也不会太大,以至于以每秒 24 帧的速度运行搜索是不可想象的。假设您在游戏 中所做的一切都是寻路,那么每帧大约需要 40 毫秒。如果您的计划器运行的时间少于(理想情况下要少得多),那么您就有合理的机会仅使用蛮力。

衡量任何搜索算法执行情况的好坏的一个很好的衡量标准是它需要扩展以找到解决方案的状态数。具有良好启发式的(编写良好的)A* 算法应该探索最少数量的状态,并且应该优于任何需要访问每个状态的搜索。考虑到这一点,Dijkstra 搜索应该比 A* 慢(因为它扩展了所有状态)。这意味着 Dikstra 搜索是使用 A* 进行规划所需时间的近似上限,即使在最坏的情况下也可能难以构建。

为了证明这不是不合理的,这里有一小段 Python 代码用于填充八连通网格(任何角度规划的合理一阶近似)和一些相关的性能结果。

import networkx as nx
import itertools
import numpy
import matplotlib.pyplot as plt

def grid_2d_8_connected(n, m):
    G = nx.Graph()
    xs = range(n)
    ys = range(m)
    dxs = [-1, 0, 1]
    dys = [-1, 0, 1]
    ds = [(dx, dy) for dx, dy in itertools.product(dxs, dys)]
    ds = [ d for d in ds if d != (0,0) ]
    for x, y in itertools.product(xs, ys):
        G.add_node( (x, y) )
    nodes = set(G.nodes())
    for x, y in itertools.product(xs, ys):
        for dx, dy in ds:
            sprime = (x+dx, y+dy)
            if sprime in nodes:
                G.add_edge((x, y), sprime)
    return G    

运行快速性能测试:

G = grid_2d_8_connected(200, 200)
%timeit nx.single_source_dijkstra_path_length(G, (0, 0))
1 loops, best of 3: 270 ms per loop

在一个稍小的网格上:

G = grid_2d_8_connected(75, 75)
%timeit nx.single_source_dijkstra_path_length(G, (0, 0))
10 loops, best of 3: 35.6 ms per loop

这表明,即使是 200 x 200 的网格,具有通用图形数据结构、Dijkstra 搜索(而不是 A*)并使用解释性语言,在这种大小的网格上进行规划也只是太慢了大约 10 倍(在我的笔记本电脑上)。

将编译代码迁移到 Python 等解释型语言的经验法则是,通常可以将性能(对于足够大的问题)提高大约 10 倍。使用解释型代码应该可以使这一速度足够快。

我的实验表明,将状态空间的每个维度的采样减少(略多于)两倍,几乎足以单独实现所需的性能。这将为您提供任何简化图表中所需状态数量的代表(上限)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 2015-04-12
    • 2014-09-16
    • 2016-03-18
    • 1970-01-01
    相关资源
    最近更新 更多