我想到了几个可能性。
更高级的路径规划
首先,你的A*搜索可能在搜索整个问题空间。例如,你住在德克萨斯州奥斯汀市,想要进入加拿大艾伯塔省的某个建筑物。一个简单的A*算法会在最终搜索加拿大之前搜索许多墨西哥和美国。
考虑创建第二层A*来解决这个问题。你首先需要找出要穿越哪些州才能到达加拿大,然后是要到达艾伯塔省,卡尔加里市,再到卡尔加里动物园等等。从某种意义上说,你从概述开始,然后填充更详细的路径。
如果你有像《上古卷轴5》那样巨大的关卡,你可能需要在城镇(多个建筑物)、地区(多个城镇)甚至国家(多个地区)之间添加路径规划层。如果你正在制作GPS系统,你甚至可能需要大陆级别的路径规划。如果我们成为星际文明,我们的太空飞船可能会包含行星、星区甚至银河系的路径规划层。
通过使用图层,您可以显著缩小搜索区域,特别是如果不同的区域不使用相同的坐标系统!(如果其中一个区域需要纬度经度,另一个需要三维笛卡尔,下一个需要通过时间维度进行路径查找,则很难估计一个A *寻路器的距离。)
更有效率的算法
在三维中查找变得更加重要,因为在搜索时需要扩展更多节点。Dijkstra搜索扩展x ^ 2个节点,而x是起点和终点之间的距离,则需要搜索x ^ 3个节点。在四维游戏中,需要更高效的路径查找。
基于网格的路径查找的好处之一是可以利用地形属性,如路径对称性。如果两条路径由相同的移动按不同顺序组成,则不需要同时查找它们。这就是一个非常高效的算法Jump Point Search发挥作用的地方。
以下是A *(左)和JPS(右)的并排比较。展开/搜索的节点以红色显示,墙壁以黑色显示:
请注意,它们都找到了相同的路径,但JPS搜索的内容少于A*的十分之一。
目前为止,我还没有看到官方的三维实现,但我已经帮助另一个用户将算法推广到多个维度。
简化网格(图)
另一种在搜索过程中消除节点的方法是在搜索之前移除它们。例如,在你可以信任一个更加愚蠢的AI找到路线的开阔区域中,你真的需要节点吗?如果你正在构建不会改变的关卡,请创建一个脚本,将其解析成仅包含重要节点的最简单网格。
这实际上被称为“离线路径规划”;基本上就是在需要找到路径之前寻找计算路径的方法。如果你的关卡将保持不变,每次更新关卡时运行脚本几分钟就可以轻松削减90%的路径查找时间。毕竟,在紧急情况出现之前,你已经完成了大部分工作。这就像在新城市里找路和在自己成长的城市里找路一样;知道地标意味着你不需要真正的地图。
类似于跳点搜索使用的“对称性破坏”的方法是由算法的创建者Daniel Harabor引入的。他在
其讲座中提到了这些方法,可以预处理级别以仅存储路径查找网格中的跳点。
巧妙的启发式方法
许多学术论文指出A*的成本函数为
f(x) = g(x) + h(x)
,这并不意味着你不能使用其他函数、乘以成本函数的权重,甚至实现领土或最近死亡的热图作为函数。这些可能会产生次优路径,但它们极大地提高了搜索的智能。当你的对手在最短路径上有一个阻塞点,并且一直轻松地消灭通过它的任何人时,谁还关心最短路径呢?更好的办法是确保AI可以安全地达到目标,而不是让它变得愚蠢。
例如,您可能希望防止算法让敌人进入秘密区域,以避免他们向玩家透露这些区域,使AI似乎对它们不知情。要实现这一点,您只需要为那些“禁止”区域内的任何点设置统一的成本函数。在这样的游戏中,敌人会在路径变得过于昂贵之后放弃追捕玩家。另一个很酷的选项是“嗅探”玩家最近去过的区域(通过暂时增加未被访问位置的成本,因为许多算法不喜欢负成本)。
如果您知道哪些地方不需要搜索,但无法在算法逻辑中实现,简单地增加它们的成本将防止不必要的搜索。有很多方法可以利用启发式来简化和通知您的路径查找,但您最大的收益将来自Jump Point Search。
编辑:Jump Point Search隐式使用与A *相同的启发式选择路径查找方向,因此您可能能够在小范围内实现启发式,但它们的成本函数不是节点的成本,而是在两个节点之间旅行的成本。(A *通常搜索相邻节点,因此节点成本和到达节点的成本之间的区别往往会崩溃。)
总结
尽管八叉树/四叉树/B树在碰撞检测中可能很有用,但它们并不适用于搜索,因为它们是基于坐标而非连接将图形分割的。将图形(词汇中的网格)分层到超级图形(区域)中是一种更有效的解决方案。
希望我有所帮助。
祝你好运!