void
AddWorkItem
(
)
Add a work item to be processed when pathfinding is paused.
The work item will be executed when it is safe to update nodes. This is defined as between the path searches. When using more threads than one, calling this often might decrease pathfinding performance due to a lot of idling in the threads. Not performance as in it will use much CPU power, but performance as in the number of paths per second will probably go down (though your framerate might actually increase a tiny bit).
You should only call this function from the main unity thread (i.e normal game code).
AstarPath.active.AddWorkItem(new AstarWorkItem(() => {
// Safe to update graphs here
var node = AstarPath.active.GetNearest(transform.position).node;
node.Walkable = false;
}));
AstarPath.active.AddWorkItem(() => {
// Safe to update graphs here
var node = AstarPath.active.GetNearest(transform.position).node;
node.position = (Int3)transform.position;
});
void
FlushGraphUpdates
()
Forces graph updates to complete in a single frame.
This will force the pathfinding threads to finish calculating the path they are currently calculating (if any) and then pause. When all threads have paused, graph updates will be performed.
Warning
Using this very often (many times per second) can reduce your fps due to a lot of threads waiting for one another. But you probably wont have to worry about that.
Note
This is almost identical to FlushWorkItems, but added for more descriptive name. This function will also override any time limit delays for graph updates. This is because graph updates are implemented using work items. So calling this function will also execute any other work items (if any are queued).
Will not do anything if there are no graph updates queued (not even execute other work items).
void
FlushWorkItems
()
Forces work items to complete in a single frame.
This will force all work items to run immidiately. This will force the pathfinding threads to finish calculating the path they are currently calculating (if any) and then pause. When all threads have paused, work items will be executed (which can be e.g graph updates).
Warning
Using this very often (many times per second) can reduce your fps due to a lot of threads waiting for one another. But you probably wont have to worry about that
Note
This is almost (note almost) identical to FlushGraphUpdates, but added for more descriptive name.
Will not do anything if there are no queued work items waiting to run.
NNInfo
GetNearest
(
)
Returns the nearest node to a position.
This method will search through all graphs and query them for the closest node to this position, and then it will return the closest one of those.
Equivalent to GetNearest(position, NNConstraint.None).
// Find the closest node to this GameObject's position
GraphNode node = AstarPath.active.GetNearest(transform.position).node;
if (node.Walkable) {
// Yay, the node is walkable, we can place a tower here or something
}
NNInfo
GetNearest
(
Vector3 | position | The point to find nodes close to |
NNConstraint | constraint | The constraint which determines which graphs and nodes are acceptable to search on. May be null, in which case all nodes will be considered acceptable. |
)
Returns the nearest node to a point using the specified NNConstraint.
Searches through all graphs for their nearest nodes to the specified position and picks the closest one. The NNConstraint can be used to specify constraints on which nodes can be chosen such as only picking walkable nodes.
GraphNode node = AstarPath.active.GetNearest(transform.position, NNConstraint.Walkable).node;
var constraint = NNConstraint.None;
// Constrain the search to walkable nodes only
constraint.constrainWalkability = true;
constraint.walkable = true;
// Constrain the search to only nodes with tag 3 or tag 5
// The 'tags' field is a bitmask
constraint.constrainTags = true;
constraint.tags = (1 << 3) | (1 << 5);
var info = AstarPath.active.GetNearest(transform.position, constraint);
var node = info.node;
var closestPoint = info.position;
Allows you to access read-only graph data in jobs safely.
You can for example use AstarPath.active.GetNearest(...) in a job.
Using AstarPath.StartPath is always safe to use in jobs even without calling this method.
When a graph update, work item, or graph scan would start, it will first block on the given dependency to ensure no race conditions occur.
If you do not call this method, then a graph update might start in the middle of your job, causing race conditions and all manner of other hard-to-diagnose bugs.
var readLock = AstarPath.active.LockGraphDataForReading();
var handle = new MyJob {
// ...
}.Schedule(readLock.dependency);
readLock.UnlockAfter(handle);
IEnumerable<Progress>
ScanAsync
(
)
Scans a particular graph asynchronously.
This is a IEnumerable, you can loop through it to get the progress
You can scan graphs asyncronously by yielding when you iterate through the returned IEnumerable. Note that this does not guarantee a good framerate, but it will allow you to at least show a progress bar while scanning.
IEnumerator Start () {
foreach (Progress progress in AstarPath.active.ScanAsync()) {
Debug.Log("Scanning... " + progress.description + " - " + (progress.progress*100).ToString("0") + "%");
yield return null;
}
}
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
IEnumerable<Progress>
ScanAsync
(
NavGraph[] | graphsToScan=null | The graphs to scan. If this parameter is null then all graphs will be scanned |
)
Scans all specified graphs asynchronously.
This is a IEnumerable, you can loop through it to get the progress
You can scan graphs asyncronously by yielding when you loop through the progress. Note that this does not guarantee a good framerate, but it will allow you to at least show a progress bar during scanning.
IEnumerator Start () {
foreach (Progress progress in AstarPath.active.ScanAsync()) {
Debug.Log("Scanning... " + progress.description + " - " + (progress.progress*100).ToString("0") + "%");
yield return null;
}
}
Note
If the graphs are already scanned, doing an async scan will temporarily cause increased memory usage, since two copies of the graphs will be kept in memory during the async scan. This may not be desirable on some platforms. A non-async scan will not cause this temporary increased memory usage.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
void
BlockUntilCalculated
(
Path | path | The path to wait for. The path must be started, otherwise an exception will be thrown. |
)
Blocks until the path has been calculated.
Normally it takes a few frames for a path to be calculated and returned. This function will ensure that the path will be calculated when this function returns and that the callback for that path has been called.
If requesting a lot of paths in one go and waiting for the last one to complete, it will calculate most of the paths in the queue (only most if using multithreading, all if not using multithreading).
Use this function only if you really need to. There is a point to spreading path calculations out over several frames. It smoothes out the framerate and makes sure requesting a large number of paths at the same time does not cause lag.
Note
Graph updates and other callbacks might get called during the execution of this function.
When the pathfinder is shutting down. I.e in OnDestroy, this function will not do anything.
int
CalculateThreadCount
(
)
Calculates number of threads to use.
If count is not Automatic, simply returns count casted to an int.
Return
An int specifying how many threads to use, 0 means a coroutine should be used for pathfinding instead of a separate thread.
If count is set to Automatic it will return a value based on the number of processors and memory for the current system. If memory is <= 512MB or logical cores are <= 1, it will return 0. If memory is <= 1024 it will clamp threads to max 2. Otherwise it will return the number of logical cores clamped to 6.
When running on WebGL this method always returns 0
bool
batchGraphUpdates = false
Throttle graph updates and batch them to improve performance.
If toggled, graph updates will batched and executed less often (specified by graphUpdateBatchingInterval).
This can have a positive impact on pathfinding throughput since the pathfinding threads do not need to be stopped as often, and it reduces the overhead per graph update. All graph updates are still applied however, they are just batched together so that more of them are applied at the same time.
However do not use this if you want minimal latency between a graph update being requested and it being applied.
This only applies to graph updates requested using the UpdateGraphs method. Not those requested using #RegisterSafeUpdate or AddWorkItem.
If you want to apply graph updates immediately at some point, you can call FlushGraphUpdates.
bool
fullGetNearestSearch = false
Do a full GetNearest search for all graphs.
Additional searches will normally only be done on the graph which in the first fast search seemed to have the closest node. With this setting on, additional searches will be done on all graphs since the first check is not always completely accurate.
More technically: GetNearestForce on all graphs will be called if true, otherwise only on the one graph which's GetNearest search returned the best node.
Usually faster when disabled, but higher quality searches when enabled.
Note
For the PointGraph this setting doesn't matter much as it has only one search mode.
float
graphUpdateBatchingInterval = 0.2F
Minimum number of seconds between each batch of graph updates.
If batchGraphUpdates is true, this defines the minimum number of seconds between each batch of graph updates.
This can have a positive impact on pathfinding throughput since the pathfinding threads do not need to be stopped as often, and it reduces the overhead per graph update. All graph updates are still applied however, they are just batched together so that more of them are applied at the same time.
Do not use this if you want minimal latency between a graph update being requested and it being applied.
This only applies to graph updates requested using the UpdateGraphs method. Not those requested using #RegisterSafeUpdate or AddWorkItem.
bool
scanOnStartup = true
If true, all graphs will be scanned during Awake.
If you disable this, you will have to call AstarPath.active.Scan() yourself to enable pathfinding. Alternatively you could load a saved graph from a file.
If a startup cache has been generated (see Saving and Loading Graphs), it always takes priority to load that instead of scanning the graphs.
This can be useful to enable if you want to scan your graphs asynchronously, or if you have a procedural world which has not been created yet at the start of the game.
ThreadCount
threadCount = ThreadCount.One
Number of pathfinding threads to use.
Multithreading puts pathfinding in another thread, this is great for performance on 2+ core computers since the framerate will barely be affected by the pathfinding at all.
None indicates that the pathfinding is run in the Unity thread as a coroutine
Automatic will try to adjust the number of threads to the number of cores and memory on the computer. Less than 512mb of memory or a single core computer will make it revert to using no multithreading.
It is recommended that you use one of the "Auto" settings that are available. The reason is that even if your computer might be beefy and have 8 cores. Other computers might only be quad core or dual core in which case they will not benefit from more than 1 or 3 threads respectively (you usually want to leave one core for the unity thread). If you use more threads than the number of cores on the computer it is mostly just wasting memory, it will not run any faster. The extra memory usage is not trivially small. Each thread needs to keep a small amount of data for each node in all the graphs. It is not the full graph data but it is proportional to the number of nodes. The automatic settings will inspect the machine it is running on and use that to determine the number of threads so that no memory is wasted.
The exception is if you only have one (or maybe two characters) active at time. Then you should probably just go with one thread always since it is very unlikely that you will need the extra throughput given by more threads. Keep in mind that more threads primarily increases throughput by calculating different paths on different threads, it will not calculate individual paths any faster.
Note that if you are modifying the pathfinding core scripts or if you are directly modifying graph data without using any of the safe wrappers (like AddWorkItem) multithreading can cause strange errors and pathfinding stopping to work if you are not careful. For basic usage (not modding the pathfinding core) it should be safe.
Note
WebGL does not support threads at all (since javascript is single-threaded) so no threads will be used on that platform.
A* Pro Feature:
This is an A* Pathfinding Project Pro feature only. This function/class/variable might not exist in the Free version of the A* Pathfinding Project or the functionality might be limited.
The Pro version can be bought here
OnGraphDelegate
OnGraphPostScan
Called for each graph after they have been scanned.
All other graphs might not have been scanned yet. In most cases it is recommended to create a custom class which inherits from Pathfinding.GraphModifier instead.
OnScanDelegate
OnLatePostScan
Called after scanning has completed fully.
This is called as the last thing in the Scan function. In most cases it is recommended to create a custom class which inherits from Pathfinding.GraphModifier instead.
OnPathDelegate
OnPathPostSearch
Called for each path after searching.
Be careful when using multithreading since this will be called from a different thread.
System.Action
OnPathsCalculated
Called right after callbacks on paths have been called.
A path's callback function runs on the main thread when the path has been calculated. This is done in batches for all paths that have finished their calculation since the last frame. This event will trigger right after a batch of callbacks have been called.
If you do not want to use individual path callbacks, you can use this instead to poll all pending paths and see which ones have completed. This is better than doing it in e.g. the Update loop, because here you will have a guarantee that all calculated paths are still valid. Immediately after this callback has finished, other things may invalidate calculated paths, like for example graph updates.
This is used by the ECS integration to update all entities' pending paths, without having to store a callback for each agent, and also to avoid the ECS synchronization overhead that having individual callbacks would entail.
OnScanDelegate
OnPostScan
Called after scanning.
This is called before applying links, flood-filling the graphs and other post processing. In most cases it is recommended to create a custom class which inherits from Pathfinding.GraphModifier instead.
Global read-write lock for graph data.
Graph data is always consistent from the main-thread's perspective, but if you are using jobs to read from graph data, you may need this.
A write lock is held automatically...
During graph updates. During async graph updates, the lock is only held once per frame while the graph update is actually running, not for the whole duration.
During work items. Async work items work similarly to graph updates, the lock is only held once per frame while the work item is actually running.
When GraphModifier events run.
When graph related callbacks, such as OnGraphsUpdated, run.
During the last step of a graph's scanning process. See ScanningStage.
To use e.g. AstarPath.active.GetNearest from an ECS job, you'll need to acquire a read lock first, and make sure the lock is only released when the job is finished.
var readLock = AstarPath.active.LockGraphDataForReading();
var handle = new MyJob {
// ...
}.Schedule(readLock.dependency);
readLock.UnlockAfter(handle);