diff options
author | chai <215380520@qq.com> | 2024-05-23 10:08:29 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-05-23 10:08:29 +0800 |
commit | 8722a9920c1f6119bf6e769cba270e63097f8e25 (patch) | |
tree | 2eaf9865de7fb1404546de4a4296553d8f68cc3b /Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs | |
parent | 3ba4020b69e5971bb0df7ee08b31d10ea4d01937 (diff) |
+ astar project
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs')
-rw-r--r-- | Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs new file mode 100644 index 0000000..b743983 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs @@ -0,0 +1,150 @@ +using UnityEngine; + +namespace Pathfinding { + /// <summary> + /// Restrict suitable nodes by if they have been searched by a FloodPath. + /// + /// Suitable nodes are in addition to the basic contraints, only the nodes which return true on a FloodPath.HasPathTo (node) call. + /// See: Pathfinding.FloodPath + /// See: Pathfinding.FloodPathTracer + /// </summary> + public class FloodPathConstraint : NNConstraint { + readonly FloodPath path; + + public FloodPathConstraint (FloodPath path) { + if (path == null) { Debug.LogWarning("FloodPathConstraint should not be used with a NULL path"); } + this.path = path; + } + + public override bool Suitable (GraphNode node) { + return base.Suitable(node) && path.HasPathTo(node); + } + } + + /// <summary> + /// Traces a path created with the Pathfinding.FloodPath. + /// + /// See Pathfinding.FloodPath for examples on how to use this path type + /// + /// [Open online documentation to see images] + /// </summary> + public class FloodPathTracer : ABPath { + /// <summary>Reference to the FloodPath which searched the path originally</summary> + protected FloodPath flood; + + protected override bool hasEndPoint => false; + + /// <summary> + /// Default constructor. + /// Do not use this. Instead use the static Construct method which can handle path pooling. + /// </summary> + public FloodPathTracer () {} + + public static FloodPathTracer Construct (Vector3 start, FloodPath flood, OnPathDelegate callback = null) { + var p = PathPool.GetPath<FloodPathTracer>(); + + p.Setup(start, flood, callback); + return p; + } + + protected void Setup (Vector3 start, FloodPath flood, OnPathDelegate callback) { + this.flood = flood; + + if (flood == null || flood.PipelineState < PathState.Returning) { + throw new System.ArgumentException("You must supply a calculated FloodPath to the 'flood' argument"); + } + + base.Setup(start, flood.originalStartPoint, callback); + nnConstraint = new FloodPathConstraint(flood); + } + + protected override void Reset () { + base.Reset(); + flood = null; + } + + /// <summary> + /// Initializes the path. + /// Traces the path from the start node. + /// </summary> + protected override void Prepare () { + if (!this.flood.IsValid(pathHandler.nodeStorage)) { + FailWithError("The flood path is invalid because nodes have been destroyed since it was calculated. Please recalculate the flood path."); + return; + } + + base.Prepare(); + + if (CompleteState == PathCompleteState.NotCalculated) { + for (uint i = 0; i < pathHandler.numTemporaryNodes; i++) { + var nodeIndex = pathHandler.temporaryNodeStartIndex + i; + ref var tempNode = ref pathHandler.GetTemporaryNode(nodeIndex); + if (tempNode.type == TemporaryNodeType.Start) { + var node = pathHandler.GetNode(tempNode.associatedNode); + + // This is guaranteed by the FloodPathConstraint + bool found = false; + for (uint k = 0; k < node.PathNodeVariants; k++) { + if (flood.GetParent(node.NodeIndex + k) != 0) { + found = true; + CompleteState = PathCompleteState.Complete; + Trace(node.NodeIndex + k); + break; + } + } + if (!found) { + FailWithError("The flood path did not contain any information about the end node. Have you modified the path's nnConstraint to an instance which does not subclass FloodPathConstraint?"); + } + return; + } + } + + FailWithError("Could not find a valid start node"); + } + } + + protected override void CalculateStep (long targetTick) { + if (CompleteState != PathCompleteState.Complete) throw new System.Exception("Something went wrong. At this point the path should be completed"); + } + + /// <summary> + /// Traces the calculated path from the start node to the end. + /// This will build an array (<see cref="path)"/> of the nodes this path will pass through and also set the <see cref="vectorPath"/> array to the <see cref="path"/> arrays positions. + /// This implementation will use the <see cref="flood"/> (FloodPath) to trace the path from precalculated data. + /// </summary> + protected override void Trace (uint fromPathNodeIndex) { + uint pathNodeIndex = fromPathNodeIndex; + int count = 0; + + while (pathNodeIndex != 0) { + if ((pathNodeIndex & FloodPath.TemporaryNodeBit) != 0) { + // Skip over temporary nodes + pathNodeIndex = flood.GetParent(pathNodeIndex & ~FloodPath.TemporaryNodeBit); + } else { + var node = pathHandler.GetNode(pathNodeIndex); + if (node == null) { + FailWithError("A node in the path has been destroyed. The FloodPath needs to be recalculated before you can use a FloodPathTracer."); + return; + } + if (!CanTraverse(node)) { + FailWithError("A node in the path is no longer walkable. The FloodPath needs to be recalculated before you can use a FloodPathTracer."); + return; + } + path.Add(node); + vectorPath.Add((Vector3)node.position); + var next = flood.GetParent(pathNodeIndex); + if (next == pathNodeIndex) { + break; + } + pathNodeIndex = next; + } + + count++; + if (count > 10000) { + Debug.LogWarning("Infinite loop? >10000 node path. Remove this message if you really have that long paths"); + break; + } + } + } + } +} |