/// <summary> /// Creates a path of from 'start' to 'end' /// </summary> void createPath() { LocalTile currentTile = tileData[(int)mapGrid.getCoordFromPosition(end.position).x, (int)mapGrid.getCoordFromPosition(end.position).y]; // Start at the end path.nodes.Clear(); // Clear any old path float distance = (start.position - currentTile.tile.position).magnitude; // Calculate the distance from the end to the start while (distance > mapGrid.tileSize) // While the distance is greater than the size of one node { path.nodes.Add(currentTile.pathNode); // Add the currentTile to the path if (currentTile.previousTile == null) // No valid path found { path.nodes.Clear(); // Clear path return; // Return early } currentTile = currentTile.previousTile; // Move backwards and set it as the next currentTile distance = (start.position - currentTile.tile.position).magnitude; // Set the distance from the new currentTile to the start } path.nodes.Reverse(); // Flip the path so it goes from start to end }
/// <summary> /// Resets all values back to default /// </summary> public void reset() { cost = 0; heuristic = 0; visited = false; inFringe = false; previousTile = null; }
private iVector2 gridDimensions; // A local copy of the map's grid dimensions. // Use this for initialization void Start() { path = gameObject.AddComponent <Path>(); // Create a path attached to this game object gridDimensions = mapGrid.getGridDimensions(); tileData = new LocalTile[gridDimensions.x, gridDimensions.y]; // Allocate size of local tileData array for (int x = 0; x < gridDimensions.x; x++) // Loop through mapGrid tiles { for (int y = 0; y < gridDimensions.y; y++) { tileData[x, y] = new LocalTile(mapGrid.getTile(new iVector2(x, y))); // Create a new localTile } } }
private LocalTile[,] tileData; // A local copy of the mapGrid tiles, with added costs, heuristics etc. // Use this for initialization void Start() { path = gameObject.AddComponent <ASPath>(); // Create a path attached to this game object tileData = new LocalTile[mapGrid.tiles.GetLength(0), mapGrid.tiles.GetLength(1)]; // Allocate size of local tileData array for (int x = 0; x < mapGrid.tiles.GetLength(0); x++) // Loop through mapGrid tiles { for (int y = 0; y < mapGrid.tiles.GetLength(1); y++) { tileData[x, y] = new LocalTile(mapGrid.tiles[x, y]); // Create a new localTile tileData[x, y].pathNode = Instantiate(nodeType); // Spawn a PathNode prefab object to be associated with the tile tileData[x, y].pathNode.transform.parent = mapGrid.transform; // Assign this PathNode as a child of the MapGrid (To not clog up the heirarchy) tileData[x, y].pathNode.transform.position = tileData[x, y].tile.position; // Move this PathNode to the position of the tile } } }
/// <summary> /// Carries out the A* search /// </summary> void search() { List <LocalTile> fringe = new List <LocalTile>(); // Stores possible next moves LocalTile currentTile = tileData[(int)mapGrid.getCoordFromPosition(start.position).x, (int)mapGrid.getCoordFromPosition(start.position).y]; // Set current tile to start while (currentTile.tile != end) // While it hasn't reached the end tile { currentTile.visited = true; // Mark tile as visited Vector2 coord = mapGrid.getCoordFromPosition(currentTile.tile.position); // Remember grid coord of tile (to easily reference neighbours) List <LocalTile> neighbours = new List <LocalTile>(); // Create a new list of its neighbours if (coord.x > 0) // Current tile isn't on left border { neighbours.Add(tileData[(int)coord.x - 1, (int)coord.y]); } if (coord.x < mapGrid.tiles.GetLength(0) - 1) // Current tile isn't on right border { neighbours.Add(tileData[(int)coord.x + 1, (int)coord.y]); } if (coord.y > 0) // Current tile isn't on bottom border { neighbours.Add(tileData[(int)coord.x, (int)coord.y - 1]); } if (coord.y < mapGrid.tiles.GetLength(1) - 1) // Current tile isn't on top border { neighbours.Add(tileData[(int)coord.x, (int)coord.y + 1]); } for (int i = 0; i < neighbours.Count; i++) // Loop through neighbours { LocalTile currentNeighbour = neighbours[i]; if (!currentNeighbour.visited && currentNeighbour.tile.walkable) // If current neighbour hasn't been visited AND is walkable { if (currentNeighbour.cost == 0 || currentNeighbour.cost > currentTile.cost + 1) // Check if a cost has not yet been established, or if the cost from this tile is cheaper { currentNeighbour.cost = currentTile.cost + 1; // Set new cost and previousTile currentNeighbour.previousTile = currentTile; if (!currentNeighbour.inFringe) // If this neighbour is not in fringe { fringe.Add(currentNeighbour); // Add it currentNeighbour.inFringe = true; } } } } if (fringe.Count == 0) // If fringe is empty, return early (to counter a possible infinite loop) { return; } // Find the next lowest costing node to move to next int lowestMove = 0; for (int i = 0; i < fringe.Count; i++) { if (fringe[i].heuristic + fringe[i].cost < fringe[lowestMove].heuristic + fringe[lowestMove].cost) { lowestMove = i; } } currentTile = fringe[lowestMove]; fringe.RemoveAt(lowestMove); currentTile.inFringe = false; } }