123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- namespace Pathfinding {
-
-
-
-
- public interface ITraversalProvider {
- bool CanTraverse(Path path, GraphNode node);
- uint GetTraversalCost(Path path, GraphNode node);
- }
-
- public static class DefaultITraversalProvider {
- public static bool CanTraverse (Path path, GraphNode node) {
- return node.Walkable && (path.enabledTags >> (int)node.Tag & 0x1) != 0;
- }
- public static uint GetTraversalCost (Path path, GraphNode node) {
- return path.GetTagPenalty((int)node.Tag) + node.Penalty;
- }
- }
-
- public abstract class Path : IPathInternals {
- #if ASTAR_POOL_DEBUG
- private string pathTraceInfo = "";
- private List<string> claimInfo = new List<string>();
- ~Path() {
- Debug.Log("Destroying " + GetType().Name + " instance");
- if (claimed.Count > 0) {
- Debug.LogWarning("Pool Is Leaking. See list of claims:\n" +
- "Each message below will list what objects are currently claiming the path." +
- " These objects have removed their reference to the path object but has not called .Release on it (which is bad).\n" + pathTraceInfo+"\n");
- for (int i = 0; i < claimed.Count; i++) {
- Debug.LogWarning("- Claim "+ (i+1) + " is by a " + claimed[i].GetType().Name + "\n"+claimInfo[i]);
- }
- } else {
- Debug.Log("Some scripts are not using pooling.\n" + pathTraceInfo + "\n");
- }
- }
- #endif
-
- protected PathHandler pathHandler;
-
-
-
-
- public OnPathDelegate callback;
-
-
-
-
-
-
- public OnPathDelegate immediateCallback;
-
- public PathState PipelineState { get; private set; }
- System.Object stateLock = new object();
-
-
-
-
- public ITraversalProvider traversalProvider;
-
- protected PathCompleteState completeState;
-
-
-
-
-
- public PathCompleteState CompleteState {
- get { return completeState; }
- protected set {
-
-
-
- lock (stateLock) {
-
- if (completeState != PathCompleteState.Error) completeState = value;
- }
- }
- }
-
-
-
-
-
- public bool error { get { return CompleteState == PathCompleteState.Error; } }
-
-
-
-
- public string errorLog { get; private set; }
-
-
-
-
- public List<GraphNode> path;
-
- public List<Vector3> vectorPath;
-
- protected PathNode currentR;
-
- public float duration;
-
- public int searchedNodes { get; protected set; }
-
-
-
-
-
-
-
- bool IPathInternals.Pooled { get; set; }
-
-
-
-
-
-
- [System.Obsolete("Has been renamed to 'Pooled' to use more widely underestood terminology", true)]
- internal bool recycled { get { return false; } }
-
-
-
-
- protected bool hasBeenReset;
-
- public NNConstraint nnConstraint = PathNNConstraint.Default;
-
-
-
-
- internal Path next;
-
- public Heuristic heuristic;
-
-
-
-
- public float heuristicScale = 1F;
-
- public ushort pathID { get; private set; }
-
- protected GraphNode hTargetNode;
-
- protected Int3 hTarget;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public int enabledTags = -1;
-
- static readonly int[] ZeroTagPenalties = new int[32];
-
-
-
-
-
- protected int[] internalTagPenalties;
-
-
-
-
- protected int[] manualTagPenalties;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public int[] tagPenalties {
- get {
- return manualTagPenalties;
- }
- set {
- if (value == null || value.Length != 32) {
- manualTagPenalties = null;
- internalTagPenalties = ZeroTagPenalties;
- } else {
- manualTagPenalties = value;
- internalTagPenalties = value;
- }
- }
- }
-
-
-
-
-
- public virtual bool FloodingPath {
- get {
- return false;
- }
- }
-
-
-
-
-
-
- public float GetTotalLength () {
- if (vectorPath == null) return float.PositiveInfinity;
- float tot = 0;
- for (int i = 0; i < vectorPath.Count-1; i++) tot += Vector3.Distance(vectorPath[i], vectorPath[i+1]);
- return tot;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public IEnumerator WaitForPath () {
- if (PipelineState == PathState.Created) throw new System.InvalidOperationException("This path has not been started yet");
- while (PipelineState != PathState.Returned) yield return null;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void BlockUntilCalculated () {
- AstarPath.BlockUntilCalculated(this);
- }
-
-
-
-
- internal uint CalculateHScore (GraphNode node) {
- uint h;
- switch (heuristic) {
- case Heuristic.Euclidean:
- h = (uint)(((GetHTarget() - node.position).costMagnitude)*heuristicScale);
-
-
-
- if (hTargetNode != null) {
- h = System.Math.Max(h, AstarPath.active.euclideanEmbedding.GetHeuristic(node.NodeIndex, hTargetNode.NodeIndex));
- }
- return h;
- case Heuristic.Manhattan:
- Int3 p2 = node.position;
- h = (uint)((System.Math.Abs(hTarget.x-p2.x) + System.Math.Abs(hTarget.y-p2.y) + System.Math.Abs(hTarget.z-p2.z))*heuristicScale);
- if (hTargetNode != null) {
- h = System.Math.Max(h, AstarPath.active.euclideanEmbedding.GetHeuristic(node.NodeIndex, hTargetNode.NodeIndex));
- }
- return h;
- case Heuristic.DiagonalManhattan:
- Int3 p = GetHTarget() - node.position;
- p.x = System.Math.Abs(p.x);
- p.y = System.Math.Abs(p.y);
- p.z = System.Math.Abs(p.z);
- int diag = System.Math.Min(p.x, p.z);
- int diag2 = System.Math.Max(p.x, p.z);
- h = (uint)((((14*diag)/10) + (diag2-diag) + p.y) * heuristicScale);
- if (hTargetNode != null) {
- h = System.Math.Max(h, AstarPath.active.euclideanEmbedding.GetHeuristic(node.NodeIndex, hTargetNode.NodeIndex));
- }
- return h;
- }
- return 0U;
- }
-
-
- public uint GetTagPenalty (int tag) {
- return (uint)internalTagPenalties[tag];
- }
- protected Int3 GetHTarget () {
- return hTarget;
- }
-
-
-
-
- public bool CanTraverse (GraphNode node) {
-
-
-
-
- if (traversalProvider != null)
- return traversalProvider.CanTraverse(this, node);
-
- unchecked { return node.Walkable && (enabledTags >> (int)node.Tag & 0x1) != 0; }
- }
-
- public uint GetTraversalCost (GraphNode node) {
- #if ASTAR_NO_TRAVERSAL_COST
- return 0;
- #else
-
- if (traversalProvider != null)
- return traversalProvider.GetTraversalCost(this, node);
- unchecked { return GetTagPenalty((int)node.Tag) + node.Penalty; }
- #endif
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public virtual uint GetConnectionSpecialCost (GraphNode a, GraphNode b, uint currentCost) {
- return currentCost;
- }
-
-
-
-
-
-
-
-
-
- public bool IsDone () {
- return PipelineState > PathState.Processing;
- }
-
- void IPathInternals.AdvanceState (PathState s) {
- lock (stateLock) {
- PipelineState = (PathState)System.Math.Max((int)PipelineState, (int)s);
- }
- }
-
-
-
-
- [System.Obsolete("Use the 'PipelineState' property instead")]
- public PathState GetState () {
- return PipelineState;
- }
-
- public void FailWithError (string msg) {
- Error();
- if (errorLog != "") errorLog += "\n" + msg;
- else errorLog = msg;
- }
-
-
-
-
- [System.Obsolete("Use FailWithError instead")]
- protected void LogError (string msg) {
- Log(msg);
- }
-
-
-
-
-
-
-
-
- [System.Obsolete("Use FailWithError instead")]
- protected void Log (string msg) {
- errorLog += msg;
- }
-
-
-
-
-
-
- public void Error () {
- CompleteState = PathCompleteState.Error;
- }
-
-
-
-
-
-
- private void ErrorCheck () {
- if (!hasBeenReset) FailWithError("Please use the static Construct function for creating paths, do not use the normal constructors.");
- if (((IPathInternals)this).Pooled) FailWithError("The path is currently in a path pool. Are you sending the path for calculation twice?");
- if (pathHandler == null) FailWithError("Field pathHandler is not set. Please report this bug.");
- if (PipelineState > PathState.Processing) FailWithError("This path has already been processed. Do not request a path with the same path object twice.");
- }
-
-
-
-
-
-
-
- protected virtual void OnEnterPool () {
- if (vectorPath != null) Pathfinding.Util.ListPool<Vector3>.Release(ref vectorPath);
- if (path != null) Pathfinding.Util.ListPool<GraphNode>.Release(ref path);
-
-
- callback = null;
- immediateCallback = null;
- traversalProvider = null;
- pathHandler = null;
- }
-
-
-
-
-
-
-
-
-
- protected virtual void Reset () {
- #if ASTAR_POOL_DEBUG
- pathTraceInfo = "This path was got from the pool or created from here (stacktrace):\n";
- pathTraceInfo += System.Environment.StackTrace;
- #endif
- if (System.Object.ReferenceEquals(AstarPath.active, null))
- throw new System.NullReferenceException("No AstarPath object found in the scene. " +
- "Make sure there is one or do not create paths in Awake");
- hasBeenReset = true;
- PipelineState = (int)PathState.Created;
- releasedNotSilent = false;
- pathHandler = null;
- callback = null;
- immediateCallback = null;
- errorLog = "";
- completeState = PathCompleteState.NotCalculated;
- path = Pathfinding.Util.ListPool<GraphNode>.Claim();
- vectorPath = Pathfinding.Util.ListPool<Vector3>.Claim();
- currentR = null;
- duration = 0;
- searchedNodes = 0;
- nnConstraint = PathNNConstraint.Default;
- next = null;
- heuristic = AstarPath.active.heuristic;
- heuristicScale = AstarPath.active.heuristicScale;
- enabledTags = -1;
- tagPenalties = null;
- pathID = AstarPath.active.GetNextPathID();
- hTarget = Int3.zero;
- hTargetNode = null;
- traversalProvider = null;
- }
-
- private List<System.Object> claimed = new List<System.Object>();
-
-
-
-
-
-
- private bool releasedNotSilent;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void Claim (System.Object o) {
- if (System.Object.ReferenceEquals(o, null)) throw new System.ArgumentNullException("o");
- for (int i = 0; i < claimed.Count; i++) {
-
- if (System.Object.ReferenceEquals(claimed[i], o))
- throw new System.ArgumentException("You have already claimed the path with that object ("+o+"). Are you claiming the path with the same object twice?");
- }
- claimed.Add(o);
- #if ASTAR_POOL_DEBUG
- claimInfo.Add(o.ToString() + "\n\nClaimed from:\n" + System.Environment.StackTrace);
- #endif
- }
-
-
-
-
- [System.Obsolete("Use Release(o, true) instead")]
- internal void ReleaseSilent (System.Object o) {
- Release(o, true);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void Release (System.Object o, bool silent = false) {
- if (o == null) throw new System.ArgumentNullException("o");
- for (int i = 0; i < claimed.Count; i++) {
-
- if (System.Object.ReferenceEquals(claimed[i], o)) {
- claimed.RemoveAt(i);
- #if ASTAR_POOL_DEBUG
- claimInfo.RemoveAt(i);
- #endif
- if (!silent) {
- releasedNotSilent = true;
- }
- if (claimed.Count == 0 && releasedNotSilent) {
- PathPool.Pool(this);
- }
- return;
- }
- }
- if (claimed.Count == 0) {
- throw new System.ArgumentException("You are releasing a path which is not claimed at all (most likely it has been pooled already). " +
- "Are you releasing the path with the same object ("+o+") twice?" +
- "\nCheck out the documentation on path pooling for help.");
- }
- throw new System.ArgumentException("You are releasing a path which has not been claimed with this object ("+o+"). " +
- "Are you releasing the path with the same object twice?\n" +
- "Check out the documentation on path pooling for help.");
- }
-
-
-
-
-
- protected virtual void Trace (PathNode from) {
-
- PathNode c = from;
- int count = 0;
- while (c != null) {
- c = c.parent;
- count++;
- if (count > 16384) {
- Debug.LogWarning("Infinite loop? >16384 node path. Remove this message if you really have that long paths (Path.cs, Trace method)");
- break;
- }
- }
-
- AstarProfiler.StartProfile("Check List Capacities");
- if (path.Capacity < count) path.Capacity = count;
- if (vectorPath.Capacity < count) vectorPath.Capacity = count;
- AstarProfiler.EndProfile();
- c = from;
- for (int i = 0; i < count; i++) {
- path.Add(c.node);
- c = c.parent;
- }
-
- int half = count/2;
- for (int i = 0; i < half; i++) {
- var tmp = path[i];
- path[i] = path[count-i-1];
- path[count - i - 1] = tmp;
- }
- for (int i = 0; i < count; i++) {
- vectorPath.Add((Vector3)path[i].position);
- }
- }
-
-
-
-
- protected void DebugStringPrefix (PathLog logMode, System.Text.StringBuilder text) {
- text.Append(error ? "Path Failed : " : "Path Completed : ");
- text.Append("Computation Time ");
- text.Append(duration.ToString(logMode == PathLog.Heavy ? "0.000 ms " : "0.00 ms "));
- text.Append("Searched Nodes ").Append(searchedNodes);
- if (!error) {
- text.Append(" Path Length ");
- text.Append(path == null ? "Null" : path.Count.ToString());
- }
- }
-
-
-
-
- protected void DebugStringSuffix (PathLog logMode, System.Text.StringBuilder text) {
- if (error) {
- text.Append("\nError: ").Append(errorLog);
- }
-
-
- if (logMode == PathLog.Heavy && !AstarPath.active.IsUsingMultithreading) {
- text.Append("\nCallback references ");
- if (callback != null) text.Append(callback.Target.GetType().FullName).AppendLine();
- else text.AppendLine("NULL");
- }
- text.Append("\nPath Number ").Append(pathID).Append(" (unique id)");
- }
-
-
-
-
-
-
- protected virtual string DebugString (PathLog logMode) {
- if (logMode == PathLog.None || (!error && logMode == PathLog.OnlyErrors)) {
- return "";
- }
-
- System.Text.StringBuilder text = pathHandler.DebugStringBuilder;
- text.Length = 0;
- DebugStringPrefix(logMode, text);
- DebugStringSuffix(logMode, text);
- return text.ToString();
- }
-
- protected virtual void ReturnPath () {
- if (callback != null) {
- callback(this);
- }
- }
-
-
-
-
-
- protected void PrepareBase (PathHandler pathHandler) {
-
-
- if (pathHandler.PathID > pathID) {
- pathHandler.ClearPathIDs();
- }
-
- this.pathHandler = pathHandler;
-
- pathHandler.InitializeForPath(this);
-
- if (internalTagPenalties == null || internalTagPenalties.Length != 32)
- internalTagPenalties = ZeroTagPenalties;
- try {
- ErrorCheck();
- } catch (System.Exception e) {
- FailWithError(e.Message);
- }
- }
-
-
-
-
- protected abstract void Prepare();
-
-
-
-
-
-
- protected virtual void Cleanup () {}
-
-
-
-
- protected abstract void Initialize();
-
- protected abstract void CalculateStep(long targetTick);
- PathHandler IPathInternals.PathHandler { get { return pathHandler; } }
- void IPathInternals.OnEnterPool () { OnEnterPool(); }
- void IPathInternals.Reset () { Reset(); }
- void IPathInternals.ReturnPath () { ReturnPath(); }
- void IPathInternals.PrepareBase (PathHandler handler) { PrepareBase(handler); }
- void IPathInternals.Prepare () { Prepare(); }
- void IPathInternals.Cleanup () { Cleanup(); }
- void IPathInternals.Initialize () { Initialize(); }
- void IPathInternals.CalculateStep (long targetTick) { CalculateStep(targetTick); }
- string IPathInternals.DebugString (PathLog logMode) { return DebugString(logMode); }
- }
-
- internal interface IPathInternals {
- PathHandler PathHandler { get; }
- bool Pooled { get; set; }
- void AdvanceState(PathState s);
- void OnEnterPool();
- void Reset();
- void ReturnPath();
- void PrepareBase(PathHandler handler);
- void Prepare();
- void Initialize();
- void Cleanup();
- void CalculateStep(long targetTick);
- string DebugString(PathLog logMode);
- }
- }
|