So I've implemented an A* algorithm in Unity C# to do some tests in order to build a 2D based game. I know there are several components out there that help you with this but I want to try myself just for the challenge.
I have basically read how the A* should behave and translated the behaviour into code. It almost works. But there are some ocassions where the adjacent tiles have exactly the same score (manhattan distance + distance from origin) and you end up with a path that leads to the destination but is not the shortest. As you can see in the image, those two adjacent tiles have the same score, but I pick up a random one at that point...(In the image below, the starting point is the cat and the red cross is the destination point. The green semi-transparent files is the calculated path)
I was thinking that since there are not too many tiles, I could calculate the 4 different paths from the 4 initial adjacent tiles, store the valid ones in a array, and then basically just use the shortest, but maybe that will be too much overhead and there is another solution?
To calculate the distance I'm using a basic calculation:
private int CalculateManhattanDistance(int x1, int x2, int y1, int y2)
{
return Mathf.Abs(x1 - x2) + Mathf.Abs(y1 - y2);
}
Maybe this help you to understand what both @Zdeněk Jelínek and @Peter Wishart have pointed out. The openSet (also named frontier), usually is a PriorityQueue . The nodes of the queue are sorted according to their priorities. The priority of a node is calculated as the sum of the cost so far (number of steps in your case) and the heuristic distance (Manhattan in your case). Therefore, as soon A* reaches the node with priority 11, it will stop to explore that path and will continue with the others (blue circle)
I recommend checking the pseudocode for A* eg on Wikipedia against your code.
Based on that pseudocode you would implement the algorithm data like this, I suspect you have simplified some of these:
var closedSet = new HashSet<GraphNode>();
var openSet = new List<GraphNode>{startNode};
var cameFrom = new Dictionary<GraphNode, GraphNode>();
var gScore = new Dictionary<GraphNode, double>();
var fScore = new Dictionary<GraphNode, double>();
When the algorithm makes a bad first choice for the heuristic, as in this test case, it will initially evaluate a move in the wrong direction. But this isn't a problem as it should:
fScore
gScore
with actual distance (via cameFrom) fScore
with actual distance plus estimated (eg Manhattan) distance to target openSet
to closedSet
This means that nodes along the "wrong" path will compute increasing actual + expected distances, to the extent that the algorithm starts choosing other open
nodes eg the "right" node from the 1st iteration.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.