/// <summary> /// Returns path in start-end order if found, otherwise an empty list /// </summary> public static List <Node> FindPath(int startX, int startY, int endX, int endY) { int searchID = Random.Range(0, int.MaxValue); // Variable definition Node startNode = Grid.GetNode(startX, startY); Node endNode = Grid.GetNode(endX, endY); Transform startObject = startNode.nodeObject; BuildingScript startBs = null; if (startObject) { startBs = startObject.GetComponent <BuildingScript>(); } if (startBs) { if (startBs.HasEntry) { startNode = startBs.EntryNode(); } } Transform endObject = endNode.nodeObject; BuildingScript endBs = null; if (endObject) { endBs = endObject.GetComponent <BuildingScript>(); } Node realEndNode = endNode; if (endBs) { if (endBs.HasEntry) { realEndNode = endBs.CenterNode(); endNode = endBs.EntryNode(); } } // if (endObject != null && (endObject.tag == "NatureObjectScript" || (endObject.tag == "Building" && endObject.GetComponent<BuildingScript>().GetBuilding().walkable))) endObject = null; Node currentNode = startNode; List <Node> path = new List <Node>(); List <Node> openlist = new List <Node>(); // Reset first node currentNode.Reset(searchID, endX, endY); // Begin with currentNode = startNode openlist.Add(currentNode); currentNode.onOpenList = true; // Count to prevent stalls int loopCount = 0; while (openlist.Count != 0) { loopCount++; if (loopCount > 10000) { break; } // Get node with minimum F-Value currentNode = GetMin(openlist); openlist.RemoveAt(0); currentNode.onOpenList = false; //openlist.Remove(currentNode); // If we have reached the endNode, we have found a path if (currentNode == endNode) { // Bcktrack path to start node path.Add(currentNode); while (currentNode != startNode) { currentNode = currentNode.GetParent(); path.Add(currentNode); } // Return path in start-end order path.Reverse(); break; } // add current node to closed list currentNode.onClosedList = true; int cx = currentNode.gridX; int cy = currentNode.gridY; // Find neighbours of currentNode int[] dx = { 1, -1, 0, 0, 1, -1, 1, -1 }; int[] dy = { 0, 0, 1, -1, 1, -1, -1, 1 }; // Weight of diagonal moves are sqrt(2) float[] weight = { 1, 1.4f }; for (int i = 0; i < 8; i++) { // Check if neghbour exists in grid if (!Grid.ValidNode(cx + dx[i], cy + dy[i])) { continue; } Node neighbour = Grid.GetNode(cx + dx[i], cy + dy[i]); if (neighbour.id != searchID) { neighbour.Reset(searchID, endX, endY); } // Only update neighbour, if not already closed and if walkable if (neighbour.onClosedList || (!neighbour.IsPath() && (neighbour.IsOccupied() && !neighbour.objectWalkable) && (startObject == null || neighbour.nodeObject != startObject || (startBs && startBs.HasEntry)) && (endObject == null || neighbour.nodeObject != endObject || (endBs && endBs.HasEntry)) && neighbour != endNode)) { continue; } // Set tentative G-Value float tg = currentNode.GetG() + weight[i / 4] * currentNode.Weight() * neighbour.Weight(); bool contains = neighbour.onOpenList; // Only update G-Value of neighbour, if lower if (contains && tg >= neighbour.GetG()) { continue; } // Update neighbour neighbour.SetParent(currentNode); neighbour.SetG(tg); // Add neighbour to openList if not already contained if (!contains) { InsertNode(openlist, neighbour); neighbour.onOpenList = true; } } } // Code for staright path /*while (true) * { * path.Add(currentNode); * * int dx = endX - currentNode.gridX; * int dy = endY - currentNode.gridY; * * int dxx = 0; int dyy = 0; * * if (dx > 0) dxx = 1; * else if (dx < 0) dxx = -1; * if (dy > 0) dyy = 1; * else if (dy < 0) dyy = -1; * * if (dx == 0 && dy == 0) break; * * currentNode = Grid.GetNode(currentNode.gridX + dxx, currentNode.gridY + dyy); * }*/ if (!startBs || !startBs.HasEntry) { path.Remove(startNode); } /*if (endNode.nodeObject != null && endNode.nodeObject.tag == "Tree") * { * path.Remove(endNode); * }*/ if (realEndNode != endNode && (endBs == null || !endBs.HasEntry)) { path.Add(realEndNode); } return(path); }