/// <summary> /// Updates the current node. /// </summary> private void UpdateNode(ref V2Node node) { if (editMode == V2Node.NodeMode.startPoint) { if (startNode != null) { if (node != startNode) { startNode.mode = V2Node.NodeMode.normal; } } startNode = node; } else if (editMode == V2Node.NodeMode.endPoint) { if (endNode != null) { if (node != endNode) { endNode.mode = V2Node.NodeMode.normal; } } endNode = node; } node.mode = editMode; }
/// <summary> /// Returns a list with all neigbouring nodes for a node. /// </summary> public List <V2Node> GetNeighbours(V2Node node) { List <V2Node> neighbours = new List <V2Node>(); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { if (x == 0 && y == 0) { continue; } int checkX = node.gridX + x; int checkY = node.gridY + y; if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY) { neighbours.Add(grid[checkX, checkY]); } } } return(neighbours); }
/// <summary> /// Returns the distance between nodeA and nodeB. /// </summary> private int GetDistance(V2Node nodeA, V2Node nodeB) { int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX); int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY); if (dstX > dstY) { return(14 * dstY + 10 * (dstX - dstY)); } return(14 * dstX + 10 * (dstY - dstX)); }
/// <summary> /// Attempts to find a path from startNode to targetNode using the A* algorithm. /// </summary> private void FindPath(V2Node startNode, V2Node targetNode) { List <V2Node> openSet = new List <V2Node>(); List <V2Node> closedSet = new List <V2Node>(); openSet.Add(startNode); while (openSet.Count > 0) { V2Node node = openSet[0]; for (int i = 1; i < openSet.Count; i++) { if (openSet[i].fCost < node.fCost || openSet[i].fCost == node.fCost) { if (openSet[i].hCost < node.hCost) { node = openSet[i]; } } } openSet.Remove(node); closedSet.Add(node); if (node == targetNode) { RetracePath(startNode, targetNode); return; } foreach (V2Node neighbour in grid.GetNeighbours(node)) { if (neighbour.mode == V2Node.NodeMode.obstacle || closedSet.Contains(neighbour)) { continue; } int newCostToNeighbour = node.gCost + GetDistance(node, neighbour); if (newCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour)) { neighbour.gCost = newCostToNeighbour; neighbour.hCost = GetDistance(neighbour, targetNode); neighbour.parent = node; if (!openSet.Contains(neighbour)) { openSet.Add(neighbour); } } } } }
/// <summary> /// Creates a new grid. /// </summary> private void CreateGrid() { grid = new V2Node[gridSizeX, gridSizeY]; for (int x = 0; x < gridSizeX; x++) { for (int y = 0; y < gridSizeY; y++) { Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius); int i = Random.Range(0, 3); V2Node.NodeMode mod = i == 0 ? V2Node.NodeMode.obstacle : V2Node.NodeMode.normal; grid[x, y] = new V2Node(mod, worldPoint, x, y); } } }
/// <summary> /// Gives a new path to the grid. /// </summary> private void RetracePath(V2Node startNode, V2Node endNode) { grid.ClearPath(); List <V2Node> path = new List <V2Node>(); V2Node currentNode = endNode.parent; while (currentNode != startNode) { path.Add(currentNode); currentNode = currentNode.parent; } path.Reverse(); grid.path = path; grid.setPath(); }