A*寻路算法生成错误路径求助:敌人穿墙追踪玩家
问题描述
我正在开发一款迷宫游戏,当玩家进入敌人的侦测范围后,敌人会通过A*寻路算法对玩家进行追踪。迷宫采用程序化(procedural)方式生成,迷宫中的每个区块都拥有包含x、z坐标的MapLocation,寻路起点为敌人位置,终点为玩家位置。但有时当玩家进入敌人范围后,寻路会无视迷宫的部分墙体直接到达玩家位置。
我已尝试使用曼哈顿距离(Manhattan's Distance)进行启发式计算,但问题并未得到解决。
寻路核心代码
IEnumerator Search(Vector3 start, Vector3 goal) { pathSuccess = false; waypoints = new Vector3[0]; Heap<Path> open = new Heap<Path>(maze.MaxSize); HashSet<Path> closed = new HashSet<Path>(); Path startNode = new Path(maze.GetMapLocation(start), 0, 0, 0, null); Path goalNode = new Path(maze.GetMapLocation(goal), 0, 0, 0, null); open.Add(startNode); lastPos = startNode; while (open.Count > 0) { if (lastPos.Equals(goalNode)) { pathSuccess = true; break; } foreach (MapLocation dir in maze.directions) { MapLocation neighbour = dir + lastPos.location; if (maze.map[neighbour.x, neighbour.z] == 1) continue; if (neighbour.x < 1 || neighbour.x >= maze.width || neighbour.z < 1 || neighbour.z >= maze.depth) continue; if (IsClosed(neighbour, closed)) continue; float G = Vector2.Distance(lastPos.location.ToVector(), neighbour.ToVector()) + lastPos.G; float H = Vector2.Distance(neighbour.ToVector(), goalNode.location.ToVector()); float F = G + H; if (!UpdateMarker(neighbour, G, H, F, lastPos, open)) open.Add(new Path(neighbour, G, H, F, lastPos)); } Path pm = open.RemoveFirst(); closed.Add(pm); lastPos = pm; } yield return null; if (pathSuccess) { waypoints = RetracePath(startNode); } PathRequestManager.Instance.FinishedProcessingPath(waypoints, pathSuccess); } bool UpdateMarker(MapLocation pos, float g, float h, float f, Path prt, Heap<Path> open) { foreach (Path p in open) { if (p.location.Equals(pos)) { p.G = g; p.H = h; p.F = f; p.parent = prt; return true; } } return false; } bool IsClosed(MapLocation marker, HashSet<Path> closed) { foreach (Path p in closed) { if (p.location.Equals(marker)) return true; } return false; } Vector3[] RetracePath(Path startNode) { Path begin = lastPos; List<Vector3> path = new List<Vector3>(); while (!startNode.Equals(begin) && begin != null) { path.Add(begin.Position(maze)); begin = begin.parent; } path.Reverse(); return path.ToArray(); } public MapLocation GetMapLocation(Vector3 position) { MapLocation mapLocation = new MapLocation((int)position.x / scale, (int)position.z / scale); return mapLocation; } public List<MapLocation> directions = new List<MapLocation>() { new MapLocation(1,0), new MapLocation(0,1), new MapLocation(-1,0), new MapLocation(0,-1) };
迷宫生成代码
public class Recursive : Maze { public override void Generate() { Generate(5, 5); } void Generate(int x, int z) { if (CountSquareNeighbours(x, z) >= 2) return; map[x, z] = 0; directions.Shuffle(); Generate(x + directions[0].x, z + directions[0].z); Generate(x + directions[1].x, z + directions[1].z); Generate(x + directions[2].x, z + directions[2].z); Generate(x + directions[3].x, z + directions[3].z); } } public byte[,] map; public virtual void Generate() { for (int z = 0; z < depth; z++) for (int x = 0; x < width; x++) { if(Random.Range(0,100) < 50) map[x, z] = 0; //1 = 墙体 0 = 通道 } }
尝试过的曼哈顿距离代码
float H = Mathf.Abs(neighbour.x - goalNode.location.x) + Mathf.Abs(neighbour.z - goalNode.location.z);
内容的提问来源于stack exchange,提问作者AND4011002849
相关产品推荐
相关产品推荐

