A* Pathfinding Project  3.8
The A* Pathfinding Project for Unity 3D
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Events Macros Groups Pages
Searching for paths


Searching for paths using a Seeker

The pathfinding can be called in a number of ways. The by far easiest method is to have Seeker component attached to the GameObject you want to call pathfinding from and then call Seeker.StartPath().
Note a Seeker will only take one pathfinding call at a time, if you send one before the previous one has been completed, it the previous one will be canceled
The Seeker will also automatically handle modifiers.

using Pathfinding;
public void Start () {
//Get the seeker component attached to this GameObject
var seeker = GetComponent<Seeker>();
// Start a new path request from the current position to a position 10 units forward.
// When the path has been calculated, it will be returned to the function OnPathComplete unless it was canceled by another path request
seeker.StartPath (transform.position, transform.position+transform.forward*10, OnPathComplete);
// Note that the path is NOT calculated at this stage
// It has just been queued for calculation
public void OnPathComplete (Path p) {
//We got our path back
if (p.error) {
// Nooo, a valid path couldn't be found
} else {
// Yay, now we can get a Vector3 representation of the path
// from p.vectorPath

A common mistake is to assume that the path is already calculated right after the StartPath call. This is however incorrect. The StartPath call will only put the path in a queue. This is done because when many units are calculating their paths at the same time, we want to spread out the path calculations over several frames to avoid FPS drops. We can also calculate the paths in other threads if multithreading has been enabled. There are of course cases where you need to calculate the path immediately. Then you can use the AstarPath.WaitForPath method. It will block until that path has been calculated. You can also wait for the path to be calculated in a coroutine using Pathfinding.Path.WaitForPath.

IEnumerator Start () {
var path = seeker.StartPath (transform.position, transform.position+transform.forward*10, OnPathComplete);
yield return StartCoroutine (path.WaitForPath());
// Now the path is calculated

You can also create your own path objects instead of using the Seeker's methods.
This will enable you to change settings on the path object before calculating it.

// Create a new path object, the last parameter is a callback function
// but it will be used internally by the seeker, so we will set it to null here
// Paths are created using the static Construct call because then it can use
// pooled paths instead of creating a new path object all the time
// which is a nice way to avoid frequent GC spikes.
var p = ABPath.Construct (transform.position, transform.position+transform.forward*10, null);
// By default, a search for the closest walkable nodes to the start and end nodes will be carried out
// but for example in a turn based game, you might not want it to search for the closest walkable node, but return an error if the target point
// was at an unwalkable node. Setting the NNConstraint to None will disable the nearest walkable node search
p.nnConstraint = NNConstraint.None;
// Start the path by sending it to the Seeker
seeker.StartPath (p, OnPathComplete);

It might seem tedious to specify the callback function every time, well, you don't have to.
There is a field on the Seeker which can be set to a function which will be called every time a path is returned. For those of you interested in performance, this is also a bit more memory efficient since it does not allocate a new delegate on the heap every time.

//Set the path callback, this should be done once
seeker.pathCallback += OnPathComplete;
//Now we can skip the callback function parameter
seeker.StartPath (transform.position, transform.position+transform.forward*10);
This callback is permanent, while the component you are calling from might not be, so it's good practise to un-register from the callback when the component is destroyed
public void OnDisable () {
seeker.pathCallback -= OnPathComplete;

A nice thing is that the callback is not limited to one function, you can have several scripts which all get a callback, or just callbacks to more than one function in the script (if you for some reason need that).
That's why I have been using + and - when registering and un-registering the callback.

Other types of paths

There are other types of paths than the standard one, for example the MultiTargetPath (Pro feature).
These can be started easily as well, especially the MultiTargetPath since the Seeker has a special function for it

//Start a multi target path, where endPoints is a Vector3[] array.
// The last parameter specifies if a path to all end points should be searched for
// or only to the closest one
seeker.StartMultiTargetPath (transform.position,endPoints,true);

The path will be returned as a Path instance, but it can be casted to for example MultiTargetPath to get all the data. A complete example of MultiTargetPath usage can be found here: Multi Target Paths

The MultiTargetPath is an A* Pathfinding Project Pro Feature, so you will get an error if you try the above code using the Free version of the project.

The generic way to start a type of path is simply

Path p = MyPathType.Construct (...); // Where MyPathType is for example MultiTargetPath
seeker.StartPath (p, OnPathComplete);

This is instead of a real consructor. It is used so that path pooling can be done more easily.

Calling AstarPath directly

There are of course cases where you want even more control of each path. Then you can call AstarPath directly. The main function you then use is AstarPath.StartPath. This can be done if you want to calculate a lot of paths at the same time. The Seeker is for agents that only have one active path at a time and if you try to request multiple paths at the same time it will only calculate the last one and cancel the rest.

The paths calculated using AstarPath.StartPath will not be post-processed. However you can call Seeker.PostProcess after a path has been calculated to post process it using themodifiers attached to a particular Seeker.
//There must be an AstarPath instance in the scene
if (AstarPath.active == null) return;
// As there is not Seeker to keep track of the callbacks, we now need to specify the callback every time again
var p = ABPath.Construct (transform.position, transform.position+transform.forward*10, OnPathComplete);
// Start the path, but call AstarPath directly
// AstarPath.active is the current AstarPath instance in the scene