123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using Pathfinding;
- #if UNITY_5_5_OR_NEWER
- using UnityEngine.Profiling;
- #endif
- #if NETFX_CORE
- using Thread = Pathfinding.WindowsStore.Thread;
- #else
- using Thread = System.Threading.Thread;
- #endif
- [ExecuteInEditMode]
- [AddComponentMenu("Pathfinding/Pathfinder")]
- [HelpURL("http://arongranberg.com/astar/documentation/stable/class_astar_path.php")]
- public class AstarPath : VersionedMonoBehaviour {
-
- public static readonly System.Version Version = new System.Version(4, 2, 18);
-
- public enum AstarDistribution { WebsiteDownload, AssetStore, PackageManager };
-
- public static readonly AstarDistribution Distribution = AstarDistribution.AssetStore;
-
-
-
-
-
-
- public static readonly string Branch = "master";
-
-
-
-
- [System.Obsolete]
- public System.Type[] graphTypes {
- get {
- return data.graphTypes;
- }
- }
-
- [UnityEngine.Serialization.FormerlySerializedAs("astarData")]
- public AstarData data;
-
-
-
-
- [System.Obsolete("The 'astarData' field has been renamed to 'data'")]
- public AstarData astarData { get { return data; } }
-
-
-
-
- #if UNITY_4_6 || UNITY_4_3
- public static new AstarPath active;
- #else
- public static AstarPath active;
- #endif
-
- public NavGraph[] graphs {
- get {
- if (data == null)
- data = new AstarData();
- return data.graphs;
- }
- }
- #region InspectorDebug
-
-
-
-
- public bool showNavGraphs = true;
-
-
-
-
-
-
-
- public bool showUnwalkableNodes = true;
-
-
-
-
-
-
-
- public GraphDebugMode debugMode;
-
-
-
-
-
-
-
-
-
- public float debugFloor = 0;
-
-
-
-
-
-
-
-
-
-
-
-
- public float debugRoof = 20000;
-
-
-
-
-
- public bool manualDebugFloorRoof = false;
-
-
-
-
-
-
-
-
- public bool showSearchTree = false;
-
-
-
-
-
-
- public float unwalkableNodeDebugSize = 0.3F;
-
-
-
-
-
-
-
-
- public PathLog logPathResults = PathLog.Normal;
- #endregion
- #region InspectorSettings
-
-
-
-
-
-
-
-
-
-
-
-
- public float maxNearestNodeDistance = 100;
-
-
-
-
- public float maxNearestNodeDistanceSqr {
- get { return maxNearestNodeDistance*maxNearestNodeDistance; }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool scanOnStartup = true;
-
-
-
-
-
-
-
-
- public bool fullGetNearestSearch = false;
-
-
-
-
-
-
-
- [System.Obsolete("This setting is discouraged, and it will be removed in a future update")]
- public bool prioritizeGraphs = false;
-
-
-
-
-
-
- [System.Obsolete("This setting is discouraged, and it will be removed in a future update")]
- public float prioritizeGraphsLimit = 1F;
-
-
-
-
- public AstarColor colorSettings;
-
-
-
-
-
- [SerializeField]
- protected string[] tagNames = null;
-
-
-
-
-
-
-
-
-
- public Heuristic heuristic = Heuristic.Euclidean;
-
-
-
-
-
-
-
-
-
-
-
-
- public float heuristicScale = 1F;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public ThreadCount threadCount = ThreadCount.One;
-
-
-
-
-
- public float maxFrameTime = 1F;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool batchGraphUpdates = false;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public float graphUpdateBatchingInterval = 0.2F;
-
-
-
-
- [System.Obsolete("This field has been renamed to 'batchGraphUpdates'")]
- public bool limitGraphUpdates { get { return batchGraphUpdates; } set { batchGraphUpdates = value; } }
-
-
-
-
- [System.Obsolete("This field has been renamed to 'graphUpdateBatchingInterval'")]
- public float maxGraphUpdateFreq { get { return graphUpdateBatchingInterval; } set { graphUpdateBatchingInterval = value; } }
- #endregion
- #region DebugVariables
- #if ProfileAstar
-
-
-
-
- public static int PathsCompleted = 0;
- public static System.Int64 TotalSearchedNodes = 0;
- public static System.Int64 TotalSearchTime = 0;
- #endif
-
-
-
-
- public float lastScanTime { get; private set; }
-
-
-
-
-
- [System.NonSerialized]
- public PathHandler debugPathData;
-
- [System.NonSerialized]
- public ushort debugPathID;
-
-
-
-
- string inGameDebugPath;
- #endregion
- #region StatusVariables
-
-
-
-
- [System.NonSerialized]
- bool isScanningBacking;
-
-
-
-
-
-
-
-
-
-
-
- public bool isScanning { get { return isScanningBacking; } private set { isScanningBacking = value; } }
-
-
-
-
-
-
- public int NumParallelThreads {
- get {
- return pathProcessor.NumThreads;
- }
- }
-
-
-
-
-
-
- public bool IsUsingMultithreading {
- get {
- return pathProcessor.IsUsingMultithreading;
- }
- }
-
-
-
-
- [System.Obsolete("Fixed grammar, use IsAnyGraphUpdateQueued instead")]
- public bool IsAnyGraphUpdatesQueued { get { return IsAnyGraphUpdateQueued; } }
-
-
-
-
-
- public bool IsAnyGraphUpdateQueued { get { return graphUpdates.IsAnyGraphUpdateQueued; } }
-
-
-
-
-
-
- public bool IsAnyGraphUpdateInProgress { get { return graphUpdates.IsAnyGraphUpdateInProgress; } }
-
-
-
-
-
- public bool IsAnyWorkItemInProgress { get { return workItems.workItemsInProgress; } }
-
-
-
-
-
-
-
-
- internal bool IsInsideWorkItem { get { return workItems.workItemsInProgressRightNow; } }
- #endregion
- #region Callbacks
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static System.Action OnAwakeSettings;
-
- public static OnGraphDelegate OnGraphPreScan;
-
- public static OnGraphDelegate OnGraphPostScan;
-
- public static OnPathDelegate OnPathPreSearch;
-
- public static OnPathDelegate OnPathPostSearch;
-
- public static OnScanDelegate OnPreScan;
-
- public static OnScanDelegate OnPostScan;
-
- public static OnScanDelegate OnLatePostScan;
-
- public static OnScanDelegate OnGraphsUpdated;
-
-
-
-
- public static System.Action On65KOverflow;
-
- [System.ObsoleteAttribute]
- public System.Action OnGraphsWillBeUpdated;
-
- [System.ObsoleteAttribute]
- public System.Action OnGraphsWillBeUpdated2;
- #endregion
- #region MemoryStructures
-
- readonly GraphUpdateProcessor graphUpdates;
-
- internal readonly HierarchicalGraph hierarchicalGraph = new HierarchicalGraph();
-
-
-
-
- public readonly NavmeshUpdates navmeshUpdates = new NavmeshUpdates();
-
- readonly WorkItemProcessor workItems;
-
- PathProcessor pathProcessor;
- bool graphUpdateRoutineRunning = false;
-
- bool graphUpdatesWorkItemAdded = false;
-
-
-
-
- float lastGraphUpdate = -9999F;
-
- PathProcessor.GraphUpdateLock workItemLock;
-
- internal readonly PathReturnQueue pathReturnQueue;
-
-
-
-
- public EuclideanEmbedding euclideanEmbedding = new EuclideanEmbedding();
- #endregion
-
-
-
-
- public bool showGraphs = false;
-
-
-
-
- private ushort nextFreePathID = 1;
- private AstarPath () {
- pathReturnQueue = new PathReturnQueue(this);
-
- pathProcessor = new PathProcessor(this, pathReturnQueue, 1, false);
- workItems = new WorkItemProcessor(this);
- graphUpdates = new GraphUpdateProcessor(this);
-
- graphUpdates.OnGraphsUpdated += () => {
- if (OnGraphsUpdated != null) {
- OnGraphsUpdated(this);
- }
- };
- }
-
-
-
-
-
-
- public string[] GetTagNames () {
- if (tagNames == null || tagNames.Length != 32) {
- tagNames = new string[32];
- for (int i = 0; i < tagNames.Length; i++) {
- tagNames[i] = ""+i;
- }
- tagNames[0] = "Basic Ground";
- }
- return tagNames;
- }
-
-
-
-
-
-
-
- public static void FindAstarPath () {
- if (Application.isPlaying) return;
- if (active == null) active = GameObject.FindObjectOfType<AstarPath>();
- if (active != null && (active.data.graphs == null || active.data.graphs.Length == 0)) active.data.DeserializeGraphs();
- }
-
-
-
-
-
- public static string[] FindTagNames () {
- FindAstarPath();
- return active != null? active.GetTagNames () : new string[1] { "There is no AstarPath component in the scene" };
- }
-
- internal ushort GetNextPathID () {
- if (nextFreePathID == 0) {
- nextFreePathID++;
- if (On65KOverflow != null) {
- System.Action tmp = On65KOverflow;
- On65KOverflow = null;
- tmp();
- }
- }
- return nextFreePathID++;
- }
- void RecalculateDebugLimits () {
- debugFloor = float.PositiveInfinity;
- debugRoof = float.NegativeInfinity;
- bool ignoreSearchTree = !showSearchTree || debugPathData == null;
- for (int i = 0; i < graphs.Length; i++) {
- if (graphs[i] != null && graphs[i].drawGizmos) {
- graphs[i].GetNodes(node => {
- if (node.Walkable && (ignoreSearchTree || Pathfinding.Util.GraphGizmoHelper.InSearchTree(node, debugPathData, debugPathID))) {
- if (debugMode == GraphDebugMode.Penalty) {
- debugFloor = Mathf.Min(debugFloor, node.Penalty);
- debugRoof = Mathf.Max(debugRoof, node.Penalty);
- } else if (debugPathData != null) {
- var rnode = debugPathData.GetPathNode(node);
- switch (debugMode) {
- case GraphDebugMode.F:
- debugFloor = Mathf.Min(debugFloor, rnode.F);
- debugRoof = Mathf.Max(debugRoof, rnode.F);
- break;
- case GraphDebugMode.G:
- debugFloor = Mathf.Min(debugFloor, rnode.G);
- debugRoof = Mathf.Max(debugRoof, rnode.G);
- break;
- case GraphDebugMode.H:
- debugFloor = Mathf.Min(debugFloor, rnode.H);
- debugRoof = Mathf.Max(debugRoof, rnode.H);
- break;
- }
- }
- }
- });
- }
- }
- if (float.IsInfinity(debugFloor)) {
- debugFloor = 0;
- debugRoof = 1;
- }
-
- if (debugRoof-debugFloor < 1) debugRoof += 1;
- }
- Pathfinding.Util.RetainedGizmos gizmos = new Pathfinding.Util.RetainedGizmos();
-
- private void OnDrawGizmos () {
-
-
-
- if (active == null) active = this;
- if (active != this || graphs == null) {
- return;
- }
-
-
-
-
-
-
-
-
-
- if (Event.current.type != EventType.Repaint) return;
- colorSettings.PushToStatic(this);
- AstarProfiler.StartProfile("OnDrawGizmos");
- if (workItems.workItemsInProgress || isScanning) {
-
-
-
-
-
- gizmos.DrawExisting();
- } else {
- if (showNavGraphs && !manualDebugFloorRoof) {
- RecalculateDebugLimits();
- }
- Profiler.BeginSample("Graph.OnDrawGizmos");
-
- for (int i = 0; i < graphs.Length; i++) {
- if (graphs[i] != null && graphs[i].drawGizmos)
- graphs[i].OnDrawGizmos(gizmos, showNavGraphs);
- }
- Profiler.EndSample();
- if (showNavGraphs) {
- euclideanEmbedding.OnDrawGizmos();
- if (debugMode == GraphDebugMode.HierarchicalNode) hierarchicalGraph.OnDrawGizmos(gizmos);
- }
- }
- gizmos.FinalizeDraw();
- AstarProfiler.EndProfile("OnDrawGizmos");
- }
- #if !ASTAR_NO_GUI
-
-
-
-
- private void OnGUI () {
- if (logPathResults == PathLog.InGame && inGameDebugPath != "") {
- GUI.Label(new Rect(5, 5, 400, 600), inGameDebugPath);
- }
- }
- #endif
-
-
-
-
-
-
- private void LogPathResults (Path path) {
- if (logPathResults != PathLog.None && (path.error || logPathResults != PathLog.OnlyErrors)) {
- string debug = (path as IPathInternals).DebugString(logPathResults);
- if (logPathResults == PathLog.InGame) {
- inGameDebugPath = debug;
- } else if (path.error) {
- Debug.LogWarning(debug);
- } else {
- Debug.Log(debug);
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- private void Update () {
-
-
-
- if (!Application.isPlaying) return;
- navmeshUpdates.Update();
-
-
- if (!isScanning) {
- PerformBlockingActions();
- }
-
- pathProcessor.TickNonMultithreaded();
-
- pathReturnQueue.ReturnPaths(true);
- }
- private void PerformBlockingActions (bool force = false) {
- if (workItemLock.Held && pathProcessor.queue.AllReceiversBlocked) {
-
-
- pathReturnQueue.ReturnPaths(false);
- Profiler.BeginSample("Work Items");
- if (workItems.ProcessWorkItems(force)) {
-
- workItemLock.Release();
- }
- Profiler.EndSample();
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("This method has been moved. Use the method on the context object that can be sent with work item delegates instead")]
- public void QueueWorkItemFloodFill () {
- throw new System.Exception("This method has been moved. Use the method on the context object that can be sent with work item delegates instead");
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("This method has been moved. Use the method on the context object that can be sent with work item delegates instead")]
- public void EnsureValidFloodFill () {
- throw new System.Exception("This method has been moved. Use the method on the context object that can be sent with work item delegates instead");
- }
-
-
-
-
-
-
-
-
-
- public void AddWorkItem (System.Action callback) {
- AddWorkItem(new AstarWorkItem(callback));
- }
-
-
-
-
-
-
-
-
-
- public void AddWorkItem (System.Action<IWorkItemContext> callback) {
- AddWorkItem(new AstarWorkItem(callback));
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void AddWorkItem (AstarWorkItem item) {
- workItems.AddWorkItem(item);
-
- if (!workItemLock.Held) {
- workItemLock = PausePathfindingSoon();
- }
- #if UNITY_EDITOR
-
- if (!Application.isPlaying) {
- FlushWorkItems();
- }
- #endif
- }
- #region GraphUpdateMethods
-
-
-
-
-
-
-
-
- public void QueueGraphUpdates () {
- if (!graphUpdatesWorkItemAdded) {
- graphUpdatesWorkItemAdded = true;
- var workItem = graphUpdates.GetWorkItem();
-
-
-
- AddWorkItem(new AstarWorkItem(() => {
- graphUpdatesWorkItemAdded = false;
- lastGraphUpdate = Time.realtimeSinceStartup;
- workItem.init();
- }, workItem.update));
- }
- }
-
-
-
-
- IEnumerator DelayedGraphUpdate () {
- graphUpdateRoutineRunning = true;
- yield return new WaitForSeconds(graphUpdateBatchingInterval-(Time.realtimeSinceStartup-lastGraphUpdate));
- QueueGraphUpdates();
- graphUpdateRoutineRunning = false;
- }
-
-
-
-
-
-
-
-
- public void UpdateGraphs (Bounds bounds, float delay) {
- UpdateGraphs(new GraphUpdateObject(bounds), delay);
- }
-
-
-
-
-
-
-
-
- public void UpdateGraphs (GraphUpdateObject ob, float delay) {
- StartCoroutine(UpdateGraphsInternal(ob, delay));
- }
-
- IEnumerator UpdateGraphsInternal (GraphUpdateObject ob, float delay) {
- yield return new WaitForSeconds(delay);
- UpdateGraphs(ob);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void UpdateGraphs (Bounds bounds) {
- UpdateGraphs(new GraphUpdateObject(bounds));
- }
-
-
-
-
-
-
-
-
-
- public void UpdateGraphs (GraphUpdateObject ob) {
- if (ob.internalStage != GraphUpdateObject.STAGE_CREATED) {
- throw new System.Exception("You are trying to update graphs using the same graph update object twice. Please create a new GraphUpdateObject instead.");
- }
- ob.internalStage = GraphUpdateObject.STAGE_PENDING;
- graphUpdates.AddToQueue(ob);
-
- if (batchGraphUpdates && Time.realtimeSinceStartup-lastGraphUpdate < graphUpdateBatchingInterval) {
- if (!graphUpdateRoutineRunning) {
- StartCoroutine(DelayedGraphUpdate());
- }
- } else {
-
- QueueGraphUpdates();
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void FlushGraphUpdates () {
- if (IsAnyGraphUpdateQueued) {
- QueueGraphUpdates();
- FlushWorkItems();
- }
- }
- #endregion
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void FlushWorkItems () {
- if (workItems.anyQueued) {
- var graphLock = PausePathfinding();
- PerformBlockingActions(true);
- graphLock.Release();
- }
- }
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("Use FlushWorkItems() instead")]
- public void FlushWorkItems (bool unblockOnComplete, bool block) {
- var graphLock = PausePathfinding();
-
- PerformBlockingActions(block);
- graphLock.Release();
- }
-
-
-
-
- [System.Obsolete("Use FlushWorkItems instead")]
- public void FlushThreadSafeCallbacks () {
- FlushWorkItems();
- }
-
-
-
-
-
-
-
- public static int CalculateThreadCount (ThreadCount count) {
- #if UNITY_WEBGL
- return 0;
- #else
- if (count == ThreadCount.AutomaticLowLoad || count == ThreadCount.AutomaticHighLoad) {
- #if ASTARDEBUG
- Debug.Log(SystemInfo.systemMemorySize + " " + SystemInfo.processorCount + " " + SystemInfo.processorType);
- #endif
- int logicalCores = Mathf.Max(1, SystemInfo.processorCount);
- int memory = SystemInfo.systemMemorySize;
- if (memory <= 0) {
- Debug.LogError("Machine reporting that is has <= 0 bytes of RAM. This is definitely not true, assuming 1 GiB");
- memory = 1024;
- }
- if (logicalCores <= 1) return 0;
- if (memory <= 512) return 0;
- if (count == ThreadCount.AutomaticHighLoad) {
- if (memory <= 1024) logicalCores = System.Math.Min(logicalCores, 2);
- } else {
-
-
-
- logicalCores /= 2;
- logicalCores = Mathf.Max(1, logicalCores);
- if (memory <= 1024) logicalCores = System.Math.Min(logicalCores, 2);
- logicalCores = System.Math.Min(logicalCores, 6);
- }
- return logicalCores;
- } else {
- int val = (int)count;
- return val;
- }
- #endif
- }
-
-
-
-
-
-
- protected override void Awake () {
- base.Awake();
- if (active != null && active != this && Application.isPlaying) {
- if (this.enabled) {
- Debug.LogWarning("Another A* component is already in the scene. More than one A* component cannot be active at the same time. Disabling this one.", this);
- }
- enabled = false;
- return;
- }
-
- active = this;
- if (FindObjectsOfType(typeof(AstarPath)).Length > 1) {
- Debug.LogError("You should NOT have more than one AstarPath component in the scene at any time.\n" +
- "This can cause serious errors since the AstarPath component builds around a singleton pattern.", this);
- }
-
- useGUILayout = false;
-
-
-
- if (!Application.isPlaying) return;
- if (OnAwakeSettings != null) {
- OnAwakeSettings();
- }
-
- GraphModifier.FindAllModifiers();
- RelevantGraphSurface.FindAllGraphSurfaces();
- InitializePathProcessor();
- InitializeProfiler();
- ConfigureReferencesInternal();
- InitializeAstarData();
-
- FlushWorkItems();
- euclideanEmbedding.dirty = true;
- navmeshUpdates.OnEnable();
- if (scanOnStartup && (!data.cacheStartup || data.file_cachedStartup == null)) {
- Scan();
- }
- }
-
- void InitializePathProcessor () {
- int numThreads = CalculateThreadCount(threadCount);
-
- if (!Application.isPlaying) numThreads = 0;
- int numProcessors = Mathf.Max(numThreads, 1);
- bool multithreaded = numThreads > 0;
- pathProcessor = new PathProcessor(this, pathReturnQueue, numProcessors, multithreaded);
- pathProcessor.OnPathPreSearch += path => {
- var tmp = OnPathPreSearch;
- if (tmp != null) tmp(path);
- };
- pathProcessor.OnPathPostSearch += path => {
- LogPathResults(path);
- var tmp = OnPathPostSearch;
- if (tmp != null) tmp(path);
- };
-
- pathProcessor.OnQueueUnblocked += () => {
- if (euclideanEmbedding.dirty) {
- euclideanEmbedding.RecalculateCosts();
- }
- };
- if (multithreaded) {
- graphUpdates.EnableMultithreading();
- }
- }
-
- internal void VerifyIntegrity () {
- if (active != this) {
- throw new System.Exception("Singleton pattern broken. Make sure you only have one AstarPath object in the scene");
- }
- if (data == null) {
- throw new System.NullReferenceException("data is null... A* not set up correctly?");
- }
- if (data.graphs == null) {
- data.graphs = new NavGraph[0];
- data.UpdateShortcuts();
- }
- }
-
-
-
-
-
-
-
- public void ConfigureReferencesInternal () {
- active = this;
- data = data ?? new AstarData();
- colorSettings = colorSettings ?? new AstarColor();
- colorSettings.PushToStatic(this);
- }
-
-
- void InitializeProfiler () {
- AstarProfiler.InitializeFastProfile(new string[14] {
- "Prepare",
- "Initialize",
- "CalculateStep",
- "Trace",
- "Open",
- "UpdateAllG",
- "Add",
- "Remove",
- "PreProcessing",
- "Callback",
- "Overhead",
- "Log",
- "ReturnPaths",
- "PostPathCallback"
- });
- }
-
-
-
-
-
-
- void InitializeAstarData () {
- data.FindGraphTypes();
- data.Awake();
- data.UpdateShortcuts();
- }
-
- void OnDisable () {
- gizmos.ClearCache();
- }
-
-
-
-
- void OnDestroy () {
-
-
-
- if (!Application.isPlaying) return;
- if (logPathResults == PathLog.Heavy)
- Debug.Log("+++ AstarPath Component Destroyed - Cleaning Up Pathfinding Data +++");
- if (active != this) return;
-
-
- PausePathfinding();
- navmeshUpdates.OnDisable();
- euclideanEmbedding.dirty = false;
- FlushWorkItems();
-
-
- pathProcessor.queue.TerminateReceivers();
- if (logPathResults == PathLog.Heavy)
- Debug.Log("Processing Possible Work Items");
-
- graphUpdates.DisableMultithreading();
-
- pathProcessor.JoinThreads();
- if (logPathResults == PathLog.Heavy)
- Debug.Log("Returning Paths");
-
- pathReturnQueue.ReturnPaths(false);
- if (logPathResults == PathLog.Heavy)
- Debug.Log("Destroying Graphs");
-
-
- if (data != null) data.OnDestroy();
- if (logPathResults == PathLog.Heavy)
- Debug.Log("Cleaning up variables");
-
-
- OnAwakeSettings = null;
- OnGraphPreScan = null;
- OnGraphPostScan = null;
- OnPathPreSearch = null;
- OnPathPostSearch = null;
- OnPreScan = null;
- OnPostScan = null;
- OnLatePostScan = null;
- On65KOverflow = null;
- OnGraphsUpdated = null;
- active = null;
- }
- #region ScanMethods
-
-
-
-
-
- [System.Obsolete("Not meaningful anymore. The HierarchicalGraph takes care of things automatically behind the scenes")]
- public void FloodFill (GraphNode seed) {
- }
-
-
-
-
-
- [System.Obsolete("Not meaningful anymore. The HierarchicalGraph takes care of things automatically behind the scenes")]
- public void FloodFill (GraphNode seed, uint area) {
- }
-
-
-
-
-
-
-
-
- [ContextMenu("Flood Fill Graphs")]
- [System.Obsolete("Avoid using. This will force a full recalculation of the connected components. In most cases the HierarchicalGraph class takes care of things automatically behind the scenes now.")]
- public void FloodFill () {
- hierarchicalGraph.RecalculateAll();
- workItems.OnFloodFill();
- }
-
-
-
-
- internal int GetNewNodeIndex () {
- return pathProcessor.GetNewNodeIndex();
- }
-
-
-
-
- internal void InitializeNode (GraphNode node) {
- pathProcessor.InitializeNode(node);
- }
-
-
-
-
-
-
-
- internal void DestroyNode (GraphNode node) {
- pathProcessor.DestroyNode(node);
- }
-
-
-
-
- [System.Obsolete("Use PausePathfinding instead. Make sure to call Release on the returned lock.", true)]
- public void BlockUntilPathQueueBlocked () {
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public PathProcessor.GraphUpdateLock PausePathfinding () {
- return pathProcessor.PausePathfinding(true);
- }
-
- PathProcessor.GraphUpdateLock PausePathfindingSoon () {
- return pathProcessor.PausePathfinding(false);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void Scan (NavGraph graphToScan) {
- if (graphToScan == null) throw new System.ArgumentNullException();
- Scan(new NavGraph[] { graphToScan });
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void Scan (NavGraph[] graphsToScan = null) {
- var prevProgress = new Progress();
- Profiler.BeginSample("Scan");
- Profiler.BeginSample("Init");
- foreach (var p in ScanAsync(graphsToScan)) {
- if (prevProgress.description != p.description) {
- #if !NETFX_CORE && UNITY_EDITOR
- Profiler.EndSample();
- Profiler.BeginSample(p.description);
-
- System.Console.WriteLine(p.description);
- prevProgress = p;
- #endif
- }
- }
- Profiler.EndSample();
- Profiler.EndSample();
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public IEnumerable<Progress> ScanAsync (NavGraph graphToScan) {
- if (graphToScan == null) throw new System.ArgumentNullException();
- return ScanAsync(new NavGraph[] { graphToScan });
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public IEnumerable<Progress> ScanAsync (NavGraph[] graphsToScan = null) {
- if (graphsToScan == null) graphsToScan = graphs;
- if (graphsToScan == null) {
- yield break;
- }
- if (isScanning) throw new System.InvalidOperationException("Another async scan is already running");
- isScanning = true;
- VerifyIntegrity();
- var graphUpdateLock = PausePathfinding();
-
-
-
-
- pathReturnQueue.ReturnPaths(false);
- if (!Application.isPlaying) {
- data.FindGraphTypes();
- GraphModifier.FindAllModifiers();
- }
- yield return new Progress(0.05F, "Pre processing graphs");
- if (OnPreScan != null) {
- OnPreScan(this);
- }
- GraphModifier.TriggerEvent(GraphModifier.EventType.PreScan);
- data.LockGraphStructure();
- Physics2D.SyncTransforms();
- var watch = System.Diagnostics.Stopwatch.StartNew();
- Profiler.BeginSample("Destroy previous nodes");
-
- for (int i = 0; i < graphsToScan.Length; i++) {
- if (graphsToScan[i] != null) {
- ((IGraphInternals)graphsToScan[i]).DestroyAllNodes();
- }
- }
- Profiler.EndSample();
-
- for (int i = 0; i < graphsToScan.Length; i++) {
-
- if (graphsToScan[i] == null) continue;
-
-
- float minp = Mathf.Lerp(0.1F, 0.8F, (float)(i)/(graphsToScan.Length));
- float maxp = Mathf.Lerp(0.1F, 0.8F, (float)(i+0.95F)/(graphsToScan.Length));
- var progressDescriptionPrefix = "Scanning graph " + (i+1) + " of " + graphsToScan.Length + " - ";
-
-
- var coroutine = ScanGraph(graphsToScan[i]).GetEnumerator();
- while (true) {
- try {
- if (!coroutine.MoveNext()) break;
- } catch {
- isScanning = false;
- data.UnlockGraphStructure();
- graphUpdateLock.Release();
- throw;
- }
- yield return coroutine.Current.MapTo(minp, maxp, progressDescriptionPrefix);
- }
- }
- data.UnlockGraphStructure();
- yield return new Progress(0.8F, "Post processing graphs");
- if (OnPostScan != null) {
- OnPostScan(this);
- }
- GraphModifier.TriggerEvent(GraphModifier.EventType.PostScan);
- FlushWorkItems();
- yield return new Progress(0.9F, "Computing areas");
- hierarchicalGraph.RecalculateIfNecessary();
- yield return new Progress(0.95F, "Late post processing");
-
-
-
- isScanning = false;
- if (OnLatePostScan != null) {
- OnLatePostScan(this);
- }
- GraphModifier.TriggerEvent(GraphModifier.EventType.LatePostScan);
- euclideanEmbedding.dirty = true;
- euclideanEmbedding.RecalculatePivots();
-
- FlushWorkItems();
-
- graphUpdateLock.Release();
- watch.Stop();
- lastScanTime = (float)watch.Elapsed.TotalSeconds;
- if (logPathResults != PathLog.None && logPathResults != PathLog.OnlyErrors) {
- Debug.Log("Scanning - Process took "+(lastScanTime*1000).ToString("0")+" ms to complete");
- }
- }
- IEnumerable<Progress> ScanGraph (NavGraph graph) {
- if (OnGraphPreScan != null) {
- yield return new Progress(0, "Pre processing");
- OnGraphPreScan(graph);
- }
- yield return new Progress(0, "");
- foreach (var p in ((IGraphInternals)graph).ScanInternal()) {
- yield return p.MapTo(0, 0.95f);
- }
- yield return new Progress(0.95f, "Assigning graph indices");
- Profiler.BeginSample("Assign graph indices");
-
- graph.GetNodes(node => node.GraphIndex = (uint)graph.graphIndex);
- Profiler.EndSample();
- if (OnGraphPostScan != null) {
- yield return new Progress(0.99f, "Post processing");
- OnGraphPostScan(graph);
- }
- }
- #endregion
- private static int waitForPathDepth = 0;
-
-
-
-
-
-
- [System.Obsolete("This method has been renamed to BlockUntilCalculated")]
- public static void WaitForPath (Path path) {
- BlockUntilCalculated(path);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public static void BlockUntilCalculated (Path path) {
- if (active == null)
- throw new System.Exception("Pathfinding is not correctly initialized in this scene (yet?). " +
- "AstarPath.active is null.\nDo not call this function in Awake");
- if (path == null) throw new System.ArgumentNullException("Path must not be null");
- if (active.pathProcessor.queue.IsTerminating) return;
- if (path.PipelineState == PathState.Created) {
- throw new System.Exception("The specified path has not been started yet.");
- }
- waitForPathDepth++;
- if (waitForPathDepth == 5) {
- Debug.LogError("You are calling the BlockUntilCalculated function recursively (maybe from a path callback). Please don't do this.");
- }
- if (path.PipelineState < PathState.ReturnQueue) {
- if (active.IsUsingMultithreading) {
- while (path.PipelineState < PathState.ReturnQueue) {
- if (active.pathProcessor.queue.IsTerminating) {
- waitForPathDepth--;
- throw new System.Exception("Pathfinding Threads seem to have crashed.");
- }
-
- Thread.Sleep(1);
- active.PerformBlockingActions(true);
- }
- } else {
- while (path.PipelineState < PathState.ReturnQueue) {
- if (active.pathProcessor.queue.IsEmpty && path.PipelineState != PathState.Processing) {
- waitForPathDepth--;
- throw new System.Exception("Critical error. Path Queue is empty but the path state is '" + path.PipelineState + "'");
- }
-
- active.pathProcessor.TickNonMultithreaded();
- active.PerformBlockingActions(true);
- }
- }
- }
- active.pathReturnQueue.ReturnPaths(false);
- waitForPathDepth--;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("Use AddWorkItem(System.Action) instead. Note the slight change in behavior (mentioned in the documentation).")]
- public static void RegisterSafeUpdate (System.Action callback) {
- active.AddWorkItem(new AstarWorkItem(callback));
- }
-
-
-
-
-
-
-
-
-
- public static void StartPath (Path path, bool pushToFront = false) {
-
- var astar = active;
- if (System.Object.ReferenceEquals(astar, null)) {
- Debug.LogError("There is no AstarPath object in the scene or it has not been initialized yet");
- return;
- }
- if (path.PipelineState != PathState.Created) {
- throw new System.Exception("The path has an invalid state. Expected " + PathState.Created + " found " + path.PipelineState + "\n" +
- "Make sure you are not requesting the same path twice");
- }
- if (astar.pathProcessor.queue.IsTerminating) {
- path.FailWithError("No new paths are accepted");
- return;
- }
- if (astar.graphs == null || astar.graphs.Length == 0) {
- Debug.LogError("There are no graphs in the scene");
- path.FailWithError("There are no graphs in the scene");
- Debug.LogError(path.errorLog);
- return;
- }
- path.Claim(astar);
-
- ((IPathInternals)path).AdvanceState(PathState.PathQueue);
- if (pushToFront) {
- astar.pathProcessor.queue.PushFront(path);
- } else {
- astar.pathProcessor.queue.Push(path);
- }
-
- if (!Application.isPlaying) {
- BlockUntilCalculated(path);
- }
- }
-
-
-
-
- static readonly NNConstraint NNConstraintNone = NNConstraint.None;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public NNInfo GetNearest (Vector3 position) {
- return GetNearest(position, NNConstraintNone);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public NNInfo GetNearest (Vector3 position, NNConstraint constraint) {
- return GetNearest(position, constraint, null);
- }
-
-
-
-
-
-
- public NNInfo GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
-
- var graphs = this.graphs;
- float minDist = float.PositiveInfinity;
- NNInfoInternal nearestNode = new NNInfoInternal();
- int nearestGraph = -1;
- if (graphs != null) {
- for (int i = 0; i < graphs.Length; i++) {
- NavGraph graph = graphs[i];
-
- if (graph == null || !constraint.SuitableGraph(i, graph)) {
- continue;
- }
- NNInfoInternal nnInfo;
- if (fullGetNearestSearch) {
-
-
- nnInfo = graph.GetNearestForce(position, constraint);
- } else {
-
-
-
- nnInfo = graph.GetNearest(position, constraint);
- }
- GraphNode node = nnInfo.node;
-
- if (node == null) {
- continue;
- }
-
- float dist = ((Vector3)nnInfo.clampedPosition-position).magnitude;
- #pragma warning disable 0618
- if (prioritizeGraphs && dist < prioritizeGraphsLimit) {
- #pragma warning restore 0618
-
- minDist = dist;
- nearestNode = nnInfo;
- nearestGraph = i;
- break;
- } else {
-
- if (dist < minDist) {
- minDist = dist;
- nearestNode = nnInfo;
- nearestGraph = i;
- }
- }
- }
- }
-
- if (nearestGraph == -1) {
- return new NNInfo();
- }
-
- if (nearestNode.constrainedNode != null) {
- nearestNode.node = nearestNode.constrainedNode;
- nearestNode.clampedPosition = nearestNode.constClampedPosition;
- }
- if (!fullGetNearestSearch && nearestNode.node != null && !constraint.Suitable(nearestNode.node)) {
-
- NNInfoInternal nnInfo = graphs[nearestGraph].GetNearestForce(position, constraint);
- if (nnInfo.node != null) {
- nearestNode = nnInfo;
- }
- }
- if (!constraint.Suitable(nearestNode.node) || (constraint.constrainDistance && (nearestNode.clampedPosition - position).sqrMagnitude > maxNearestNodeDistanceSqr)) {
- return new NNInfo();
- }
-
- return new NNInfo(nearestNode);
- }
-
-
-
-
- public GraphNode GetNearest (Ray ray) {
- if (graphs == null) return null;
- float minDist = Mathf.Infinity;
- GraphNode nearestNode = null;
- Vector3 lineDirection = ray.direction;
- Vector3 lineOrigin = ray.origin;
- for (int i = 0; i < graphs.Length; i++) {
- NavGraph graph = graphs[i];
- graph.GetNodes(node => {
- Vector3 pos = (Vector3)node.position;
- Vector3 p = lineOrigin+(Vector3.Dot(pos-lineOrigin, lineDirection)*lineDirection);
- float tmp = Mathf.Abs(p.x-pos.x);
- tmp *= tmp;
- if (tmp > minDist) return;
- tmp = Mathf.Abs(p.z-pos.z);
- tmp *= tmp;
- if (tmp > minDist) return;
- float dist = (p-pos).sqrMagnitude;
- if (dist < minDist) {
- minDist = dist;
- nearestNode = node;
- }
- return;
- });
- }
- return nearestNode;
- }
- }
|