From 8722a9920c1f6119bf6e769cba270e63097f8e25 Mon Sep 17 00:00:00 2001 From: chai <215380520@qq.com> Date: Thu, 23 May 2024 10:08:29 +0800 Subject: + astar project --- .../Pathfinders/FloodPathTracer.cs | 150 +++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Pathfinders/FloodPathTracer.cs') 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 { + /// + /// 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 + /// + 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); + } + } + + /// + /// 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] + /// + public class FloodPathTracer : ABPath { + /// Reference to the FloodPath which searched the path originally + protected FloodPath flood; + + protected override bool hasEndPoint => false; + + /// + /// Default constructor. + /// Do not use this. Instead use the static Construct method which can handle path pooling. + /// + public FloodPathTracer () {} + + public static FloodPathTracer Construct (Vector3 start, FloodPath flood, OnPathDelegate callback = null) { + var p = PathPool.GetPath(); + + 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; + } + + /// + /// Initializes the path. + /// Traces the path from the start node. + /// + 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"); + } + + /// + /// Traces the calculated path from the start node to the end. + /// This will build an array ( of the nodes this path will pass through and also set the array to the arrays positions. + /// This implementation will use the (FloodPath) to trace the path from precalculated data. + /// + 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; + } + } + } + } +} -- cgit v1.1-26-g67d0