public static void ComputePath(MovementController movingElement, Vector2Int goal, PathReadyFunc onComplete) { movingElement.StartCoroutine(ComputePathAsync(movingElement, goal, onComplete)); }
private static IEnumerator ComputePathAsync(MovementController movingElement, Vector2Int goal, PathReadyFunc onComplete) { Vector2Int start = movingElement.gridElement.position; Vector2Int?closestGoal = FindClosestToGoal(goal); if (closestGoal.HasValue) { goal = closestGoal.Value; } else { onComplete.Invoke(null); yield break; } List <Vector2Int> openSet = new List <Vector2Int> { start }; Dictionary <Vector2Int, Vector2Int> cameFrom = new Dictionary <Vector2Int, Vector2Int>(); Dictionary <Vector2Int, float> gScore = new Dictionary <Vector2Int, float> { [start] = 0 }; Dictionary <Vector2Int, float> fScore = new Dictionary <Vector2Int, float> { [start] = H(start, goal) }; float lastFrameTime = Time.realtimeSinceStartup; while (openSet.Count > 0) { Vector2Int current = openSet[0]; foreach (Vector2Int i in openSet) { if (fScore[i] < fScore[current]) { current = i; } } if (current == goal) { onComplete.Invoke(ReconstructPath(cameFrom, current)); yield break; } openSet.Remove(current); foreach (Vector2Int neighbor in AvailableNeighbors(movingElement, current)) { if (!gScore.ContainsKey(neighbor)) { gScore[neighbor] = Mathf.Infinity; } float tentativeScore = gScore[current] + Vector2Int.Distance(current, neighbor); if (tentativeScore < gScore[neighbor]) { cameFrom[neighbor] = current; gScore[neighbor] = tentativeScore; fScore[neighbor] = gScore[neighbor] + H(neighbor, goal); if (!openSet.Contains(neighbor)) { openSet.Add(neighbor); } } } float frameRate = Application.targetFrameRate == -1 ? 60.0f : Application.targetFrameRate; if (Time.realtimeSinceStartup - lastFrameTime >= 1 / frameRate) { lastFrameTime = Time.realtimeSinceStartup; yield return(null); } } onComplete.Invoke(null); }