我正在计算网格中的寻路,我已经构建了一个统一的网格。节点(3D网格中的单元格)接近我认为的“平稳的”#34;表面我标记为可访问,它们用于我的寻路。为了获得大量的细节(比如能够找到小楼梯的情况),我的网格中的可访问单元的数量已经变得非常大,数千个大型建筑物。 (每个网格单元格为0.5x0.5x0.5 m,网格是具有真实世界尺寸的房间)。即使我只使用网格中的一小部分实际单元进行寻路,但巨大的ammount会降低算法的速度。除此之外,它工作正常,并使用加权曼哈顿距离启发式找到通过网格的正确路径。
想象一下,我的网格看起来就像那样,网格在里面(可以是或多或少的立方体,但它总是立方体),但是路径查找不会在所有小立方体上计算,只有少数标记为可访问(通常在网格底部但可能取决于网格有多少层。
我希望减少寻路的搜索空间...我已经看过像HPA *这样做的聚类以及像马尔科夫这样的其他聚类算法,但它们似乎最适合用于节点图而不是网格。一个显而易见的解决方案是仅增加构建网格的小立方体的大小,但是在路径查找中我会丢失很多细节,并且它不会那么健壮。我怎么能聚集这些小立方体?这是我进行寻路时典型搜索空间的样子(蓝色可访问,绿色是路径):
如你所见,有很多立方体可供搜索,因为它们之间的距离非常小! 不要紧,网格现在是一种不理想的寻路解决方案。
有没有人知道如何减少我必须搜索的网格中的多维数据集量,以及在减少空间后如何访问邻居? :)现在它只在扩展搜索空间时查看最近的邻居。
答案 0 :(得分:6)
有几种可能性浮现在脑海中。
首先,您的A *搜索可能正在搜索整个问题空间。例如,你住在德克萨斯州的奥斯汀,想进入加拿大艾伯塔省某个特定的建筑物。在最终搜索加拿大建筑之前,一个简单的A *算法将搜索许多墨西哥和美国。
考虑创建第二层A *来解决这个问题。你首先要找出哪些州到达加拿大,然后去哪些省份到达艾伯塔省,然后到达卡尔加里,然后到达卡尔加里动物园。从某种意义上说,你从概述开始,然后用更详细的路径填写它。
如果您有很多级别,例如天际,您可能需要在城镇(多个建筑物),区域(多个城镇)甚至国家(多个地区)之间添加寻路层。如果您正在制作GPS系统,您甚至可能需要大陆。如果我们成为星际,我们的宇宙飞船可能包含行星,扇区甚至星系的寻路层。
通过使用图层,您可以显着缩小搜索范围,特别是如果不同区域不使用相同的坐标系统! (如果其中一个区域需要经度 - 纬度,另一个需要经过时间维度的寻找,那么很难估计一个A *探路者的距离。)
在3维中找到有效的算法变得更加重要,因为在搜索时有更多的节点需要扩展。扩展x ^ 2个节点的Dijkstra搜索将搜索x ^ 3,其中x是起点和目标之间的距离。 4D游戏在寻路方面需要更高的效率。
基于网格的寻路的一个好处是,您可以利用路径对称等拓扑属性。如果两条路径由不同顺序的相同移动组成,则您不需要找到它们。这是一个名为Jump Point Search的非常有效的算法。
这是A *(左)和JPS(右)的并排比较。扩展/搜索节点显示为红色,墙壁为黑色:
请注意,他们都找到相同的路径,但JPS很容易搜索到不到A *所做的十分之一。
截至目前,我还没有看到官方的三维实施,但我已帮助其他用户generalize the algorithm to multiple dimensions。
在搜索过程中摆脱节点的另一种方法是在搜索之前删除它们。例如,您是否真的需要在开放区域中的节点,您可以信任更愚蠢的AI来找到它的方式?如果要构建不会更改的级别,请创建一个脚本,将其解析为仅包含重要节点的最简单网格。
实际上这叫做“离线寻路”'基本上找到在需要找到它们之前计算路径的方法。如果您的级别保持不变,则每次更新级别时运行脚本几分钟将轻松减少90%的路径查找时间。毕竟,在紧急工作之前,你完成了大部分工作。就像你在长大的城市中找到自己的方式一样;了解地标意味着你并不需要地图。
“对称性破坏”的类似方法。 Jump Point Search的使用是由算法的创建者Daniel Harabor引入的。它们在his lectures之一中被提及,并允许您预处理级别以在路径寻找网格中存储仅跳转点。
许多学术论文指出A *的成本函数是f(x) = g(x) + h(x)
,这并不能说明你可以使用其他函数,乘以成本函数的权重,甚至实施领土或近期死亡的热图作为功能。这些可能会创建次优路径,但它们可以极大地提高搜索的智能性。当你的对手有一个阻塞点并且很容易派遣任何人通过它时,谁在乎最短的路径?最好确定AI能够安全地达到目标,而不是让它变得愚蠢。
例如,您可能希望阻止算法让敌人访问秘密区域,以便他们避免将其暴露给玩家,以便他们AI似乎不知道它们。实现这一目标所需要的只是一个统一的成本函数,用于那些“禁区”内的任何一点。区域。在这样的游戏中,在路径变得过于昂贵之后,敌人会放弃追捕玩家。另一个很酷的选择是香味'最近玩家的区域(暂时增加未访问位置的成本,因为许多算法不喜欢负成本)。
如果您知道自己赢得了哪些地方不需要搜索,但无法在您的算法逻辑中实施,那么简单地增加费用就可以避免不必要的搜索。有很多方法可以利用启发式方法来简化和通知你的寻路,但你最大的收获来自跳跃点搜索。
编辑:跳转点搜索使用与A *相同的启发式隐式选择寻路方向,因此您可以在很小程度上实现启发式算法,但是它们的成本函数不会成为节点的成本,但是而且,在两个节点之间旅行的成本。 (A *通常搜索相邻的节点,因此节点成本和前往它的成本之间的区别往往会中断。)
尽管八叉树/四树/ b树在碰撞检测中很有用,但它们并不适用于搜索,因为它们根据坐标对图形进行分区。不是它的联系。将图形(词汇表中的网格)分层为超级图形(区域)是一种更有效的解决方案。
希望我已经涵盖了您认为有用的任何内容。 祝你好运!