/// <summary> /// called when path from here to goal is found /// </summary> private void OnPathToGoalFound() { pathToGoal = pathShower.pathSave; // placing this here makes it so that enemy spawn // loop only begins after path is found StartCoroutine(EnemySpawnLoop()); }
// make with board/tilemap static FoundPath RunDjikstras(MapTile _start, MapTile _goal, List <MapTile> allTiles) { // setup MapTile currentNode = _start; currentNode.calculatedCost = 0; List <MapTile> unvisitedNodes = new List <MapTile>(allTiles); while (unvisitedNodes.Count > 0 && currentNode != _goal) { unvisitedNodes.Remove(currentNode); Debug.Assert(currentNode.Connections.Count <= 4); // take out later // all neighbors foreach (MapTile neighbor in currentNode.Connections) { if (neighbor.calculatedCost > 1000000) { int newCost = currentNode.calculatedCost + neighbor.Data.traversalCost; if (newCost < neighbor.calculatedCost) { neighbor.calculatedCost = newCost; neighbor.previousTile = currentNode; } } } // next current currentNode = unvisitedNodes[0]; foreach (MapTile currentCheck in unvisitedNodes) { if (currentCheck.calculatedCost < currentNode.calculatedCost) { currentNode = currentCheck; } } } List <MapTile> _path = GeneratePath(_start, _goal, false); FoundPath toReturn = new FoundPath { start = _start, goal = _goal, path = _path }; // cleanup foreach (MapTile tile in allTiles) { tile.ResetPathfinding(); } return(toReturn); }
private bool FindPath(Vector3 startPos, Vector3 endPos, float clampTol) { // re-number all the pathpoints Dictionary <GameObject, int> IDs = new Dictionary <GameObject, int>(); int N = 0; foreach (GameObject pathPoint in pathPoints) { IDs[pathPoint] = N; ++N; } // init path matrix float[,] path = new float[pathPoints.Count, pathPoints.Count]; for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { path[i, j] = maxDistance; } } foreach (GameObject pathEdge in pathEdges) { GameObject p0 = pathEdge.GetComponent <PathEdge>().P0(); GameObject p1 = pathEdge.GetComponent <PathEdge>().P1(); int id0 = IDs[p0]; int id1 = IDs[p1]; path[id0, id1] = Distance(p0, p1); path[id1, id0] = path[id0, id1]; } //int s = IDs[FindNearestPathPoint(startPos)]; //int t = IDs[FindNearestPathPoint(endPos)]; GameObject es = FindNearestPathEdge(startPos); GameObject et = FindNearestPathEdge(endPos); Debug.Log(es + " " + et); if (es == null || et == null) { return(false); } // move in the same "zone" if (es == et) { //Debug.Log("same"); recentPath = new FoundPath(); Vector3 validEndPos = Clamp(et.GetComponent <PathEdge>(), endPos); if (Vector3.Distance(validEndPos, endPos) > clampTol) { return(false); } recentPath.Insert(new DirectedPathEdgeOnPositions(startPos, validEndPos)); } else { float[] d = new float[N]; for (int i = 0; i < N; ++i) { d[i] = maxDistance; } int esp0 = IDs[es.GetComponent <PathEdge>().P0()]; int esp1 = IDs[es.GetComponent <PathEdge>().P1()]; int etp0 = IDs[et.GetComponent <PathEdge>().P0()]; int etp1 = IDs[et.GetComponent <PathEdge>().P1()]; d[esp0] = Vector3.Distance(es.GetComponent <PathEdge>().P0().transform.position, startPos); d[esp1] = Vector3.Distance(es.GetComponent <PathEdge>().P1().transform.position, startPos); //d[s] = 0; prePathPoint = new int[N]; List <int> queue = new List <int>(); bool[] inQueue = new bool[N]; for (int i = 0; i < N; ++i) { inQueue[i] = false; prePathPoint[i] = -1; } // SPFA starts from two points int head = 0; int tail = 0; queue.Add(esp0); ++tail; inQueue[esp0] = true; queue.Add(esp1); ++tail; inQueue[esp1] = true; //queue.Add(s); //++tail; //inQueue[s] = true; while (head < tail) { int o = queue[head]; inQueue[o] = false; for (int i = 0; i < N; ++i) { if (d[i] > d[o] + path[o, i]) { d[i] = d[o] + path[o, i]; if (!inQueue[i]) { queue.Add(i); inQueue[i] = true; ++tail; prePathPoint[i] = o; } } } ++head; } // two end points - choose the nearer one float endDis0 = d[etp0] + Vector3.Distance(et.GetComponent <PathEdge>().P0().transform.position, endPos); float endDis1 = d[etp1] + Vector3.Distance(et.GetComponent <PathEdge>().P1().transform.position, endPos); //Debug.Log(endDis0 + " " + endDis1); if (endDis0 >= maxDistance && endDis1 >= maxDistance) { return(false); } // construct result path recentPath = new PointBasedFoundPath(); int curPoint = etp0; if (endDis0 > endDis1) { curPoint = etp1; } Vector3 validEndPos = Clamp(et.GetComponent <PathEdge>(), endPos); if (Vector3.Distance(validEndPos, endPos) > clampTol) { return(false); } recentPath.Insert(new DirectedPathEdgeOnObjectAndPosition(pathPoints[curPoint], validEndPos)); while (true) { int prePoint = prePathPoint[curPoint]; if (prePoint != -1) { recentPath.Insert(new DirectedPathEdgeOnTwoObjects(pathPoints[prePoint], pathPoints[curPoint])); } else { break; } curPoint = prePathPoint[curPoint]; } recentPath.Insert(new DirectedPathEdgeOnPositionAndObject(startPos, pathPoints[curPoint])); } return(true); }
public ICollection <Vector3> GetPath(Vector3 from, Vector3 to, Vector3 halfExtends) { FoundPath fp = foundPaths.Where(x => x.From == from && x.To == to && x.HalfExtends == halfExtends).FirstOrDefault(); if (fp != null) { return(fp.Path.ToList()); } List <PathfindingTile> closedList = new List <PathfindingTile>(); List <PathfindingTile> openList = new List <PathfindingTile>(); openList.Add(new PathfindingTile(from, EstimateCosts(from, to), null)); int limit = 10000; int limitCounter = 0; while (openList.Where(x => x.Position == to).Count() == 0) { PathfindingTile tileToCheck = openList.OrderBy(x => x.EstimatedCosts).First(); PathfindingTile[] neigh = GetNeighbors(tileToCheck, to, halfExtends); openList.AddRange(neigh.Where(o => closedList.Where(c => c.Position == o.Position).Count() == 0)); openList.Remove(tileToCheck); closedList.Add(tileToCheck); limitCounter++; if (limitCounter > limit) { break; } } List <Vector3> points = new List <Vector3>(); PathfindingTile nextTile = openList.OrderBy(x => x.EstimatedCosts).First(); bool pathFound = false; while (!pathFound) { points.Add(nextTile.Position); if (nextTile.LastTile == null || nextTile.LastTile.Position == from) { pathFound = true; break; } nextTile = nextTile.LastTile; } int counter = 0; List <KeyValuePair <int, Vector3> > pointsWithOrder = new List <KeyValuePair <int, Vector3> >(); for (var i = points.Count - 1; i >= 0; i--) { pointsWithOrder.Add(new KeyValuePair <int, Vector3>(counter, points[i])); counter++; } List <Vector3> path = pointsWithOrder.OrderBy(x => x.Key).Select(x => x.Value).ToList(); foundPaths.Add(new FoundPath(from, to, halfExtends, path.ToArray())); return(path); }
public void GreedyManhattanAlgorithm(Vector2Int start, Vector2Int end) { Queue <Vector2Int> frontier = new Queue <Vector2Int>(); frontier.Enqueue(start); Dictionary <Vector2Int, Vector2Int> cameFrom = new Dictionary <Vector2Int, Vector2Int>(); cameFrom.Add(start, start); List <Vector2Int> visited = new List <Vector2Int>(); while (frontier.Count != 0) { Vector2Int current = frontier.Dequeue(); visited.Add(current); pathFollowed.Add(current); List <Vector2Int> neighbours = GetNeighbours(current); Vector2Int cameFromLocal; cameFrom.TryGetValue(current, out cameFromLocal); neighbours.Remove(cameFromLocal); //Remove visited neighbours List <Vector2Int> neighboursToRemove = new List <Vector2Int>(); foreach (Vector2Int neighbour in neighbours) { if (visited.Contains(neighbour)) { neighboursToRemove.Add(neighbour); } } foreach (Vector2Int neighbour in neighboursToRemove) { neighbours.Remove(neighbour); FoundPath.Remove(current); } //Sort neighbours so the element closest to the end (Using Manhattan distance) is first neighbours.Sort(delegate(Vector2Int a, Vector2Int b) { int aManhattan = PathfinderHelper.ManhattanDistance(a.x, a.y, end.x, end.y); int bManhattan = PathfinderHelper.ManhattanDistance(b.x, b.y, end.x, end.y); if (aManhattan > bManhattan) { return(1); } if (aManhattan < bManhattan) { return(-1); } return(0); }); //If there is a neighbour, check him. Otherwise, backtrack if (neighbours.Count > 0) { Vector2Int nextNeighbour = neighbours[0]; FoundPath.Add(current); if (nextNeighbour == end) { pathFollowed.Add(nextNeighbour); return; } else { frontier.Enqueue(nextNeighbour); cameFrom.Add(nextNeighbour, current); visited.Add(current); } } else { frontier.Enqueue(cameFromLocal); FoundPath.Remove(current); } } }
IEnumerator PathfindingAnimation() { if (null != currentTile.previousTile) { currentTile.previousTile.tileStatus = TileStatus.clear; } while (unvsitedTiles.Count > 0 && currentTile != goal) { unvsitedTiles.Remove(currentTile); Debug.Assert(currentTile.Connections.Count <= 4); // take out later // all neighbors foreach (MapTile neighbor in currentTile.Connections) { if (neighbor.calculatedCost > 1000000) { int newCost = currentTile.calculatedCost + neighbor.Data.traversalCost; if (newCost < neighbor.calculatedCost) { neighbor.calculatedCost = newCost; neighbor.previousTile = currentTile; } } } // currentTile.tileStatus = TileStatus.clear; foreach (MapTile tile in currentTile.Connections) { tile.tileStatus = TileStatus.none; } // next current currentTile = unvsitedTiles[0]; foreach (MapTile currentCheck in unvsitedTiles) { if (currentCheck.calculatedCost < currentTile.calculatedCost) { currentTile = currentCheck; currentTile.tileStatus = TileStatus.current; foreach (MapTile neighbor in currentTile.Connections) { neighbor.tileStatus = TileStatus.next; } } } yield return(new WaitForSeconds(waitTime)); } List <MapTile> path = Pathfinder.GeneratePath(start, goal, false); FoundPath toReturn = new FoundPath { start = start, goal = goal, path = path }; // cleanup foreach (MapTile tile in allTiles) { tile.ResetPathfinding(); } pathSave = toReturn; pathFound?.Invoke(); }