Hi all. I've just implemented A* pathfinding for my project and it works great. I can click my unit and get them to navigate to any point on my tile map. I am just having a little trouble with limiting the movement range of my units. I figure it's something like the code below. Start with the tile the unit is on, then iterate through its neighbours, add them to the moveableArea list, then iterate through the moveableArea list again to find their neighbours, and then limit the amount of iterations based on a formula using the Units max movement distance. But I can't quite figure out how to do it properly - all my attempts end up half-baked: So I've removed all failed coding attempts, and the below script currently just returns EVERY tile on the board. I would really appreciate any help possible. Thanks very much for your time! map.tiles is a list of ALL tiles in the scene. Neighbour is just a custom class that holds some extra data I need. Neighbour.id is the position of the neighbouring tile in map.tiles Code (csharp): //The final list of tiles the unit can move to List<Tile> moveableArea = new List<Tile>(); void GetMoveableArea(Unit unit) { // The distance the unit can move is based on its speed stat int distance = unit.speed.level; //Add the first tile to the search area moveableArea.Add(map.tiles[unit.tilePosition]); for (int i = 0; i < moveableArea.Count; i++) { for (int n = 0; n < 4; n++) { Neighbour neighbour = moveableArea[i].neighbours[n]; // If the neighbour is not a null tile, its walkable, // and its not already in our moveable area if (!neighbour.nullTile && neighbour.walkable && !moveableArea.Contains(map.tiles[neighbour.id])) { // Use the neighbours ID to get the tile moveableArea.Add(map.tiles[neighbour.id]); } } } }
You don't want to add things to a list while you are iterating over it. In this case, that's moveableArea. That will, in almost all cases, cause some unexpected behavior, as you can tell. The code is a bit unclear to me. But what you are describing seems like it should just be a simple recursive function. I threw together some pseudocode REAL quick, maybe it can help out. Code (CSharp): List<Tile> tiles = new List<Tile>(startTile); // iterate over tiles. Find neighbors for those tiles, then iterate over those neighbors. This is the recursive part. List neighbors = FindNeighbors(tile, moveableArea); moveableArea.Add(neighbors); // In the end your recursive function would return a list of all collected tiles // FindNeighbors List<Tile> FindNeighbors(Tile tile, List<tiles> moveableArea) { // return a list containing the neighbors of "tile" // but filter out the ones that are already contained in "moveableArea" }
I like to try something very simple to troubleshoot first. Something like the following code with Debug.Log statements throughout to see where the problem is Code (CSharp): void GetMoveableArea(Unit unit) { int distance = unit.speed.level; Tile occupiedTile = map.tiles[unit.tilePosition]; moveableArea.Clear(); MADD(occupiedTile); foreach (Tile n in occupiedTile.neighbours) MADD(n); } void MADD(Tile t) { if (!moveableArea.Contains(t)) moveableArea.Add(t); }
Hey EdGunther, thanks a lot for taking the time to respond! I managed to get a bit of help from Reddit, who reminded me that A* uses a cost system for figuring out paths. So all I had to do was measure the movement cost from my origin tile to each of the neighbours, and then simply add any tiles that were under a specific cost amount. Got it working great now!
Hey! Don't know if you still remember but, how did you get the movement cost from the neighbors? Did you use the pathfinding? Could you link the reddit post? Because what I did was calculate the manhattan distance between them. However, some of them go outside of not walkable zones