A* Pathfinding Project  4.1.20
The A* Pathfinding Project for Unity 3D
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Events Macros Groups Pages
AstarAI.cs

Full source for the simple AI written in the get started guide .It should be attached to a GameObject with a Seeker and a CharacterController also attached.


using UnityEngine;
// Note this line, if it is left out, the script won't know that the class 'Path' exists and it will throw compiler errors
// This line should always be present at the top of scripts which use pathfinding
using Pathfinding;
public class AstarAI : MonoBehaviour {
public Transform targetPosition;
private Seeker seeker;
private CharacterController controller;
public Path path;
public float speed = 2;
public float nextWaypointDistance = 3;
private int currentWaypoint = 0;
public float repathRate = 0.5f;
private float lastRepath = float.NegativeInfinity;
public bool reachedEndOfPath;
public void Start () {
seeker = GetComponent<Seeker>();
// If you are writing a 2D game you can remove this line
// and use the alternative way to move sugggested further below.
controller = GetComponent<CharacterController>();
}
public void OnPathComplete (Path p) {
Debug.Log("A path was calculated. Did it fail with an error? " + p.error);
// Path pooling. To avoid unnecessary allocations paths are reference counted.
// Calling Claim will increase the reference count by 1 and Release will reduce
// it by one, when it reaches zero the path will be pooled and then it may be used
// by other scripts. The ABPath.Construct and Seeker.StartPath methods will
// take a path from the pool if possible. See also the documentation page about path pooling.
p.Claim(this);
if (!p.error) {
if (path != null) path.Release(this);
path = p;
// Reset the waypoint counter so that we start to move towards the first point in the path
currentWaypoint = 0;
} else {
p.Release(this);
}
}
public void Update () {
if (Time.time > lastRepath + repathRate && seeker.IsDone()) {
lastRepath = Time.time;
// Start a new path to the targetPosition, call the the OnPathComplete function
// when the path has been calculated (which may take a few frames depending on the complexity)
seeker.StartPath(transform.position, targetPosition.position, OnPathComplete);
}
if (path == null) {
// We have no path to follow yet, so don't do anything
return;
}
// Check in a loop if we are close enough to the current waypoint to switch to the next one.
// We do this in a loop because many waypoints might be close to each other and we may reach
// several of them in the same frame.
reachedEndOfPath = false;
// The distance to the next waypoint in the path
float distanceToWaypoint;
while (true) {
// If you want maximum performance you can check the squared distance instead to get rid of a
// square root calculation. But that is outside the scope of this tutorial.
distanceToWaypoint = Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]);
if (distanceToWaypoint < nextWaypointDistance) {
// Check if there is another waypoint or if we have reached the end of the path
if (currentWaypoint + 1 < path.vectorPath.Count) {
currentWaypoint++;
} else {
// Set a status variable to indicate that the agent has reached the end of the path.
// You can use this to trigger some special code if your game requires that.
reachedEndOfPath = true;
break;
}
} else {
break;
}
}
// Slow down smoothly upon approaching the end of the path
// This value will smoothly go from 1 to 0 as the agent approaches the last waypoint in the path.
var speedFactor = reachedEndOfPath ? Mathf.Sqrt(distanceToWaypoint/nextWaypointDistance) : 1f;
// Direction to the next waypoint
// Normalize it so that it has a length of 1 world unit
Vector3 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized;
// Multiply the direction by our desired speed to get a velocity
Vector3 velocity = dir * speed * speedFactor;
// Move the agent using the CharacterController component
// Note that SimpleMove takes a velocity in meters/second, so we should not multiply by Time.deltaTime
controller.SimpleMove(velocity);
// If you are writing a 2D game you may want to remove the CharacterController and instead modify the position directly
// transform.position += velocity * Time.deltaTime;
}
}