public float GetHeuristic(MazeNode nodeStart, MazeNode nodeEnd, AStarMode mode, float rand = 0f) { Vector2 start = new Vector2(nodeStart.transform.position.x, nodeStart.transform.position.z); Vector2 end = new Vector2(nodeEnd.transform.position.x, nodeEnd.transform.position.z); if (mode == AStarMode.euclidian) { return Vector2.Distance(start, end); } if (mode == AStarMode.manhattan) { return Mathf.Abs(start.x - end.x) + Mathf.Abs(start.y - end.y); } if (mode == AStarMode.randomEuclidian) { return Vector2.Distance(start, end) + Random.Range(0f, rand); } if (mode == AStarMode.randomManhattan) { return Mathf.Abs(start.x - end.x) + Mathf.Abs(start.y - end.y) + Random.Range(0f, rand); } else { Debug.LogWarning("Unspecified Heuristic!"); return 0f; } }
IEnumerator AStarAgent(AStarMode mode = AStarMode.manhattan, float rand = 5f) { int timer = 0; List<MazeNode> closed = new List<MazeNode>(); List<MazeNode> open = new List<MazeNode>(); open.Add(startNode); startNode.g = 0f; while (open.Count > 0) { MazeNode bestNode = open[0]; foreach (MazeNode node in open) { if (node.f < bestNode.f) { bestNode = node; } } if (bestNode == exitNode) { break; } foreach (MazeNode node in bestNode.currentConnections) { if (node == null) { continue; } if (node.closed) { continue; } open.Add(node); float newG = bestNode.g + GetHeuristic(bestNode, node, AStarMode.manhattan, 0f); if (node.g > newG) { node.g = newG; node.h = GetHeuristic(node, exitNode, mode, rand); node.f = node.g + node.h; node.cameFrom = bestNode; } } closed.Add(bestNode); bestNode.closed = true; if (debugColors) { bestNode.floorRenderer.material = debugCyan; } open.Remove(bestNode); timer++; if (timer >= aStarSpeed) { timer = 0; yield return new WaitForSeconds(0.01f); } } //Reset came from foreach(MazeNode node in closed) { node.ResetAStarVariables(); } foreach(MazeNode node in open) { node.ResetAStarVariables(); } yield break; }
public List<MazeNode> AStar(MazeNode start, MazeNode end, AStarMode mode = AStarMode.manhattan, float rand = 5f, bool ignoreWalls = false) { List<MazeNode> path = new List<MazeNode>(); List<MazeNode> closed = new List<MazeNode>(); List<MazeNode> open = new List<MazeNode>(); open.Add(start); start.g = 0f; while (open.Count > 0) { MazeNode bestNode = open[0]; foreach (MazeNode node in open) { if (node.f < bestNode.f) { bestNode = node; } } if (bestNode == end) { break; } if (ignoreWalls) { foreach (MazeNode node in bestNode.connections) { if (node == null) { continue; } if (node.closed) { continue; } open.Add(node); float newG = bestNode.g + GetHeuristic(bestNode, node, AStarMode.manhattan, 0f); if (node.g > newG) { node.g = newG; node.h = GetHeuristic(node, end, mode, rand); node.f = node.g + node.h; node.cameFrom = bestNode; } } } else { foreach (MazeNode node in bestNode.currentConnections) { if (node == null) { continue; } if (node.closed) { continue; } open.Add(node); float newG = bestNode.g + GetHeuristic(bestNode, node, AStarMode.manhattan, 0f); if (node.g > newG) { node.g = newG; node.h = GetHeuristic(node, end, mode, rand); node.f = node.g + node.h; node.cameFrom = bestNode; } } } closed.Add(bestNode); bestNode.closed = true; open.Remove(bestNode); } //Determine path path.Add(end); MazeNode next = end; while (next != start) { next = next.cameFrom; path.Add(next); } path.Reverse(); //Reset came from foreach(MazeNode node in closed) { node.ResetAStarVariables(); } foreach(MazeNode node in open) { node.ResetAStarVariables(); } return path; }