引言
在开发游戏时,我很想创建第一个NPC。 于是出现了一个问题,即如何使NPC绕墙而不是“闯入”。
通过互联网,我发现了以下算法:
- 广泛搜索(BFS,广度优先搜索)
- Dijkstra的算法(Dijkstra)
- 星号“带星号的A”
- 按首个最佳匹配进行搜索(最佳优先搜索)
- IDA (具有迭代加深的A )
- 跳点搜索
我决定尝试在体素3D网格上实现A *。

算法说明
*逐步查找从初始顶点到最终顶点的所有路径,直到找到最小的路径为止。 像所有明智的搜索算法一样,他首先关注“似乎”导致目标的那些路线。 贪婪算法(也是首个最佳匹配的搜索算法)与众不同之处在于,在选择顶点时,除其他因素外,它还考虑了到达该顶点的整个路径。
实作
由于算法需要“节点”-确定路径的点,因此我们编写了节点的类结构:
节点代码:public enum EMoveAction { walk, jump, fall, swim }; public class PathPoint {
小类构造函数: private PathPoint NewPathPoint(Vector3 point, float pathLenghtFromStart, float heuristicEstimatePathLenght, EMoveAction moveAction) { PathPoint a = new PathPoint(); a.point = point; a.pathLenghtFromStart = pathLenghtFromStart; a.heuristicEstimatePathLenght = heuristicEstimatePathLenght; a.moveAction = moveAction; return a; } private PathPoint NewPathPoint(Vector3 point, float pathLenghtFromStart, float heuristicEstimatePathLenght, EMoveAction moveAction, PathPoint ppoint) { PathPoint a = new PathPoint(); a.point = point; a.pathLenghtFromStart = pathLenghtFromStart; a.heuristicEstimatePathLenght = heuristicEstimatePathLenght; a.moveAction = moveAction; a.cameFrom = ppoint; return a; }
接下来,路径搜索设置的结构将派上用场:
路径搜索设置代码: public struct SPathFinderType {
此外,“世界”是一种数据库类,用于存储有关地图块的信息。 您的实施方式可能有所不同。
获取路径的路径搜索功能结果: public List<PathPoint> GetPathToTarget(Vector3 beginPoint, Vector3 targetPoint, World worldData, SPathFinderType pfType) { List<PathPoint> path = new List<PathPoint>();
收盘点
ClosePoint函数仅取决于World类的实现,它将所有可能的路径添加到其中的打开点列表中,并从该列表中删除当前点(将其关闭)。 我将在前四个方向给出一个“闭合点”的例子。
警告一大堆代码 private List<PathPoint> ClosePoint(int index, List<PathPoint> openPoints, List<PathPoint> closedPoints, World worldData, SPathFinderType pfType, Vector3 targetPoint) { List<PathPoint> newOpenPoints = openPoints; PathPoint lastPoint = openPoints[index];
最佳化
通过简单地划分从起点到当前点的路径,我们将节点数减少了很多倍,并使它变得更加贪婪。
return this.heuristicEstimatePathLenght + this.pathLenghtFromStart /2;
总结
优点:
缺点:
绿色显示打开的节点列表,红色显示到目标的路径,蓝色显示关闭的节点。
文学作品
https://tproger.ru/articles/pathfindings/
https://ru.wikipedia.org/wiki/A*