/// <summary>Internal method to start a path and mark it as the currently active path</summary> private void StartPathInternal(Path p, OnPathDelegate callback) { p.callback += onPathDelegate; p.enabledTags = traversableTags; p.tagPenalties = tagPenalties; // Cancel a previously requested path is it has not been processed yet and also make sure that it has not been recycled and used somewhere else if (path != null && path.PipelineState <= PathState.Processing && path.CompleteState != PathCompleteState.Error && lastPathID == path.pathID) { path.FailWithError("Canceled path because a new one was requested.\n" + "This happens when a new path is requested from the seeker when one was already being calculated.\n" + "For example if a unit got a new order, you might request a new path directly instead of waiting for the now" + " invalid path to be calculated. Which is probably what you want.\n" + "If you are getting this a lot, you might want to consider how you are scheduling path requests."); } // No callback will be sent for the canceled path // Set p as the active path path = p; tmpPathCallback = callback; // Save the path id so we can make sure that if we cancel a path (see above) it should not have been recycled yet. lastPathID = path.pathID; // Pre process the path RunModifiers(ModifierPass.PreProcess, path); // Send the request to the pathfinder AstarPath.StartPath(path); }
// Token: 0x060021C7 RID: 8647 RVA: 0x001903CC File Offset: 0x0018E5CC private void StartPathInternal(Path p, OnPathDelegate callback) { MultiTargetPath multiTargetPath = p as MultiTargetPath; if (multiTargetPath != null) { OnPathDelegate[] array = new OnPathDelegate[multiTargetPath.targetPoints.Length]; for (int i = 0; i < array.Length; i++) { array[i] = this.onPartialPathDelegate; } multiTargetPath.callbacks = array; p.callback = (OnPathDelegate)Delegate.Combine(p.callback, new OnPathDelegate(this.OnMultiPathComplete)); } else { p.callback = (OnPathDelegate)Delegate.Combine(p.callback, this.onPathDelegate); } p.enabledTags = this.traversableTags; p.tagPenalties = this.tagPenalties; if (this.path != null && this.path.PipelineState <= PathState.Processing && this.path.CompleteState != PathCompleteState.Error && this.lastPathID == (uint)this.path.pathID) { this.path.FailWithError("Canceled path because a new one was requested.\nThis happens when a new path is requested from the seeker when one was already being calculated.\nFor example if a unit got a new order, you might request a new path directly instead of waiting for the now invalid path to be calculated. Which is probably what you want.\nIf you are getting this a lot, you might want to consider how you are scheduling path requests."); } this.path = p; this.tmpPathCallback = callback; this.lastPathID = (uint)this.path.pathID; this.RunModifiers(Seeker.ModifierPass.PreProcess, this.path); AstarPath.StartPath(this.path, false); }
public void RecalculateCosts() { if (this.pivots == null) { this.RecalculatePivots(); } if (this.mode == HeuristicOptimizationMode.None) { return; } this.pivotCount = 0; for (int i = 0; i < this.pivots.Length; i++) { if (this.pivots[i] != null && (this.pivots[i].Destroyed || !this.pivots[i].Walkable)) { throw new Exception("Invalid pivot nodes (destroyed or unwalkable)"); } } if (this.mode != HeuristicOptimizationMode.RandomSpreadOut) { for (int j = 0; j < this.pivots.Length; j++) { if (this.pivots[j] == null) { throw new Exception("Invalid pivot nodes (null)"); } } } Debug.Log("Recalculating costs..."); this.pivotCount = this.pivots.Length; Action <int> startCostCalculation = null; startCostCalculation = delegate(int k) { GraphNode pivot = this.pivots[k]; FloodPath fp = null; fp = FloodPath.Construct(pivot, null); fp.immediateCallback = delegate(Path _p) { _p.Claim(this); MeshNode meshNode = pivot as MeshNode; uint costOffset = 0u; int k; if (meshNode != null && meshNode.connectionCosts != null) { for (k = 0; k < meshNode.connectionCosts.Length; k++) { costOffset = Math.Max(costOffset, meshNode.connectionCosts[k]); } } NavGraph[] graphs = AstarPath.active.graphs; for (int m = graphs.Length - 1; m >= 0; m--) { graphs[m].GetNodes(delegate(GraphNode node) { int num6 = node.NodeIndex * this.pivotCount + k; this.EnsureCapacity(num6); PathNode pathNode = fp.pathHandler.GetPathNode(node); if (costOffset > 0u) { this.costs[num6] = ((pathNode.pathID != fp.pathID || pathNode.parent == null) ? 0u : Math.Max(pathNode.parent.G - costOffset, 0u)); } else { this.costs[num6] = ((pathNode.pathID != fp.pathID) ? 0u : pathNode.G); } return(true); }); } if (this.mode == HeuristicOptimizationMode.RandomSpreadOut && k < this.pivots.Length - 1) { int num = -1; uint num2 = 0u; int num3 = this.maxNodeIndex / this.pivotCount; for (int n = 1; n < num3; n++) { uint num4 = 1073741824u; for (int num5 = 0; num5 <= k; num5++) { num4 = Math.Min(num4, this.costs[n * this.pivotCount + num5]); } GraphNode node2 = fp.pathHandler.GetPathNode(n).node; if ((num4 > num2 || num == -1) && node2 != null && !node2.Destroyed && node2.Walkable) { num = n; num2 = num4; } } if (num == -1) { Debug.LogError("Failed generating random pivot points for heuristic optimizations"); return; } this.pivots[k + 1] = fp.pathHandler.GetPathNode(num).node; Debug.Log(string.Concat(new object[] { "Found node at ", this.pivots[k + 1].position, " with score ", num2 })); startCostCalculation(k + 1); } _p.Release(this); }; AstarPath.StartPath(fp, true); }; if (this.mode != HeuristicOptimizationMode.RandomSpreadOut) { for (int l = 0; l < this.pivots.Length; l++) { startCostCalculation(l); } } else { startCostCalculation(0); } this.dirty = false; }
public void RecalculateCosts() { if (pivots == null) { RecalculatePivots(); } if (mode == HeuristicOptimizationMode.None) { return; } pivotCount = 0; for (int i = 0; i < pivots.Length; i++) { if (pivots[i] != null && (pivots[i].Destroyed || !pivots[i].Walkable)) { throw new System.Exception("Invalid pivot nodes (destroyed or unwalkable)"); } } if (mode != HeuristicOptimizationMode.RandomSpreadOut) { for (int i = 0; i < pivots.Length; i++) { if (pivots[i] == null) { throw new System.Exception("Invalid pivot nodes (null)"); } } } Debug.Log("Recalculating costs..."); pivotCount = pivots.Length; System.Action <int> startCostCalculation = null; startCostCalculation = delegate(int k) { GraphNode pivot = pivots[k]; FloodPath fp = null; fp = FloodPath.Construct(pivot); fp.immediateCallback = delegate(Path _p) { // Handle path pooling _p.Claim(this); // When paths are calculated on navmesh based graphs // the costs are slightly modified to match the actual target and start points // instead of the node centers // so we have to remove the cost for the first and last connection // in each path var mn = pivot as MeshNode; uint costOffset = 0; if (mn != null && mn.connectionCosts != null) { for (int i = 0; i < mn.connectionCosts.Length; i++) { costOffset = System.Math.Max(costOffset, mn.connectionCosts[i]); } } var graphs = AstarPath.active.graphs; // Process graphs in reverse order to raise probability that we encounter large NodeIndex values quicker // to avoid resizing the internal array too often for (int j = graphs.Length - 1; j >= 0; j--) { graphs[j].GetNodes(delegate(GraphNode node) { int idx = node.NodeIndex * pivotCount + k; EnsureCapacity(idx); PathNode pn = fp.pathHandler.GetPathNode(node); if (costOffset > 0) { costs[idx] = pn.pathID == fp.pathID && pn.parent != null ? System.Math.Max(pn.parent.G - costOffset, 0) : 0; } else { costs[idx] = pn.pathID == fp.pathID ? pn.G : 0; } return(true); }); } if (mode == HeuristicOptimizationMode.RandomSpreadOut && k < pivots.Length - 1) { int best = -1; uint bestScore = 0; // Actual number of nodes int totCount = maxNodeIndex / pivotCount; // Loop through all nodes for (int j = 1; j < totCount; j++) { // Find the minimum distance from the node to all existing pivot points uint mx = 1 << 30; for (int p = 0; p <= k; p++) { mx = System.Math.Min(mx, costs[j * pivotCount + p]); } // Pick the node which has the largest minimum distance to the existing pivot points // (i.e pick the one furthest away from the existing ones) GraphNode node = fp.pathHandler.GetPathNode(j).node; if ((mx > bestScore || best == -1) && node != null && !node.Destroyed && node.Walkable) { best = j; bestScore = mx; } } if (best == -1) { Debug.LogError("Failed generating random pivot points for heuristic optimizations"); return; } pivots[k + 1] = fp.pathHandler.GetPathNode(best).node; Debug.Log("Found node at " + pivots[k + 1].position + " with score " + bestScore); startCostCalculation(k + 1); } // Handle path pooling _p.Release(this); }; AstarPath.StartPath(fp, true); }; if (mode != HeuristicOptimizationMode.RandomSpreadOut) { // All calculated in paralell for (int i = 0; i < pivots.Length; i++) { startCostCalculation(i); } } else { // Recursive and serial startCostCalculation(0); } dirty = false; }
public void RecalculateCosts() { if (this.pivots == null) { this.RecalculatePivots(); } if (this.mode == HeuristicOptimizationMode.None) { return; } this.pivotCount = 0; for (int i = 0; i < this.pivots.Length; i++) { if (this.pivots[i] != null && (this.pivots[i].Destroyed || !this.pivots[i].Walkable)) { throw new Exception("Invalid pivot nodes (destroyed or unwalkable)"); } } if (this.mode != HeuristicOptimizationMode.RandomSpreadOut) { for (int j = 0; j < this.pivots.Length; j++) { if (this.pivots[j] == null) { throw new Exception("Invalid pivot nodes (null)"); } } } Debug.Log("Recalculating costs..."); this.pivotCount = this.pivots.Length; Action <int> startCostCalculation = null; int numComplete = 0; OnPathDelegate onComplete = delegate(Path path) { numComplete++; if (numComplete == this.pivotCount) { Debug.Log("Grid graph special case!"); this.ApplyGridGraphEndpointSpecialCase(); } }; startCostCalculation = delegate(int pivotIndex) { GraphNode pivot = this.pivots[pivotIndex]; FloodPath floodPath = null; floodPath = FloodPath.Construct(pivot, onComplete); floodPath.immediateCallback = delegate(Path _p) { _p.Claim(this); MeshNode meshNode = pivot as MeshNode; uint costOffset = 0u; if (meshNode != null && meshNode.connections != null) { for (int l = 0; l < meshNode.connections.Length; l++) { costOffset = Math.Max(costOffset, meshNode.connections[l].cost); } } NavGraph[] graphs = AstarPath.active.graphs; for (int m = graphs.Length - 1; m >= 0; m--) { graphs[m].GetNodes(delegate(GraphNode node) { int num6 = node.NodeIndex * this.pivotCount + pivotIndex; this.EnsureCapacity(num6); PathNode pathNode = ((IPathInternals)floodPath).PathHandler.GetPathNode(node); if (costOffset > 0u) { this.costs[num6] = ((pathNode.pathID != floodPath.pathID || pathNode.parent == null) ? 0u : Math.Max(pathNode.parent.G - costOffset, 0u)); } else { this.costs[num6] = ((pathNode.pathID != floodPath.pathID) ? 0u : pathNode.G); } }); } if (this.mode == HeuristicOptimizationMode.RandomSpreadOut && pivotIndex < this.pivots.Length - 1) { if (this.pivots[pivotIndex + 1] == null) { int num = -1; uint num2 = 0u; int num3 = this.maxNodeIndex / this.pivotCount; for (int n = 1; n < num3; n++) { uint num4 = 1073741824u; for (int num5 = 0; num5 <= pivotIndex; num5++) { num4 = Math.Min(num4, this.costs[n * this.pivotCount + num5]); } GraphNode node2 = ((IPathInternals)floodPath).PathHandler.GetPathNode(n).node; if ((num4 > num2 || num == -1) && node2 != null && !node2.Destroyed && node2.Walkable) { num = n; num2 = num4; } } if (num == -1) { Debug.LogError("Failed generating random pivot points for heuristic optimizations"); return; } this.pivots[pivotIndex + 1] = ((IPathInternals)floodPath).PathHandler.GetPathNode(num).node; } startCostCalculation(pivotIndex + 1); } _p.Release(this, false); }; AstarPath.StartPath(floodPath, true); }; if (this.mode != HeuristicOptimizationMode.RandomSpreadOut) { for (int k = 0; k < this.pivots.Length; k++) { startCostCalculation(k); } } else { startCostCalculation(0); } this.dirty = false; }
public void RecalculateCosts() { #if !AstarFree && !ASTAR_NO_EUCLIDEAN_EMBEDDING if (pivots == null) { RecalculatePivots(); } if (mode == HeuristicOptimizationMode.None) { return; } pivotCount = 0; for (int i = 0; i < pivots.Length; i++) { if (pivots[i] != null && (pivots[i].Destroyed || !pivots[i].Walkable)) { throw new System.Exception("Invalid pivot nodes (destroyed or unwalkable)"); } } if (mode != HeuristicOptimizationMode.RandomSpreadOut) { for (int i = 0; i < pivots.Length; i++) { if (pivots[i] == null) { throw new System.Exception("Invalid pivot nodes (null)"); } } } Debug.Log("Recalculating costs..."); pivotCount = pivots.Length; System.Action <int> startCostCalculation = null; int numComplete = 0; OnPathDelegate onComplete = (Path path) => { numComplete++; if (numComplete == pivotCount) { // Last completed path ApplyGridGraphEndpointSpecialCase(); } }; startCostCalculation = (int pivotIndex) => { GraphNode pivot = pivots[pivotIndex]; FloodPath floodPath = null; floodPath = FloodPath.Construct(pivot, onComplete); floodPath.immediateCallback = (Path _p) => { // Handle path pooling _p.Claim(this); // When paths are calculated on navmesh based graphs // the costs are slightly modified to match the actual target and start points // instead of the node centers // so we have to remove the cost for the first and last connection // in each path var meshNode = pivot as MeshNode; uint costOffset = 0; if (meshNode != null && meshNode.connections != null) { for (int i = 0; i < meshNode.connections.Length; i++) { costOffset = System.Math.Max(costOffset, meshNode.connections[i].cost); } } var graphs = AstarPath.active.graphs; // Process graphs in reverse order to raise probability that we encounter large NodeIndex values quicker // to avoid resizing the internal array too often for (int j = graphs.Length - 1; j >= 0; j--) { graphs[j].GetNodes(node => { int idx = node.NodeIndex * pivotCount + pivotIndex; EnsureCapacity(idx); PathNode pn = ((IPathInternals)floodPath).PathHandler.GetPathNode(node); if (costOffset > 0) { costs[idx] = pn.pathID == floodPath.pathID && pn.parent != null ? System.Math.Max(pn.parent.G - costOffset, 0) : 0; } else { costs[idx] = pn.pathID == floodPath.pathID ? pn.G : 0; } }); } if (mode == HeuristicOptimizationMode.RandomSpreadOut && pivotIndex < pivots.Length - 1) { // If the next pivot is null // then find the node which is furthest away from the earlier // pivot points if (pivots[pivotIndex + 1] == null) { int best = -1; uint bestScore = 0; // Actual number of nodes int totCount = maxNodeIndex / pivotCount; // Loop through all nodes for (int j = 1; j < totCount; j++) { // Find the minimum distance from the node to all existing pivot points uint mx = 1 << 30; for (int p = 0; p <= pivotIndex; p++) { mx = System.Math.Min(mx, costs[j * pivotCount + p]); } // Pick the node which has the largest minimum distance to the existing pivot points // (i.e pick the one furthest away from the existing ones) GraphNode node = ((IPathInternals)floodPath).PathHandler.GetPathNode(j).node; if ((mx > bestScore || best == -1) && node != null && !node.Destroyed && node.Walkable) { best = j; bestScore = mx; } } if (best == -1) { Debug.LogError("Failed generating random pivot points for heuristic optimizations"); return; } pivots[pivotIndex + 1] = ((IPathInternals)floodPath).PathHandler.GetPathNode(best).node; } // Start next path startCostCalculation(pivotIndex + 1); } // Handle path pooling _p.Release(this); }; AstarPath.StartPath(floodPath, true); }; if (mode != HeuristicOptimizationMode.RandomSpreadOut) { // All calculated in parallel for (int i = 0; i < pivots.Length; i++) { startCostCalculation(i); } } else { // Recursive and serial startCostCalculation(0); } #endif dirty = false; }