A* Pathfinding Project  4.1.2
The A* Pathfinding Project for Unity 3D
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Events Macros Groups Pages
Wandering AI Tutorial

Tutorial on how to make a wandering AI.

There are several methods for making a wandering AI. They differ in both quality and performance. There is no obvious best solution, different methods will suite different games better. For each method I have listed some advantages and disadvantages.

Method 1: Random point inside a circle

The easiest method for picking a point to move to is simply to pick a random point within a specific distance around the character.

Vector3 PickRandomPoint () {
var point = Random.insideUnitSphere * radius;
point.y = 0;
point += transform.position;
return point;
}

If you are using one of the included movement scripts you can for example change the destination of the AI whenever it has reached the end of its current path:

using UnityEngine;
using System.Collections;
using Pathfinding;
public class WanderingDestinationSetter : MonoBehaviour {
public float radius = 20;
IAstarAI ai;
void Start () {
ai = GetComponent<IAstarAI>();
}
Vector3 PickRandomPoint () {
var point = Random.insideUnitSphere * radius;
point.y = 0;
point += ai.position;
return point;
}
void Update () {
// Update the destination of the AI if
// the AI is not already calculating a path and
// the ai has reached the end of the path or it has no path at all
if (!ai.pathPending && (ai.targetReached || !ai.hasPath)) {
ai.destination = PickRandomPoint();
ai.SearchPath();
}
}
}

You can attach the script above to any GameObject with one of the built-in movement scripts (e.g AIPath/RichAI/AILerp). Make sure that you do not have any other components attached that also try to set the destination of the AI (e.g the AIDestinationSetter component).

See Also
Pathfinding.IAstarAI
Random.insideUnitSphere

Advantages

  • Very fast.
  • Simple code.
  • Works reasonably well for all graph types.

Disadvantages

  • Ignores the actual distance to the point which means it can produce very long paths if the world is not very open (see the video above).
  • Has a slight bias towards points close to walls/obstacles as any points that were generated inside the obstacles would have to be snapped to the closest point on the graph.

Misc

  • Ignores penalties when picking points (penalties will be taken into account when searching for a path to the point though).

Method 2: The RandomPath type

The RandomPath type is a path type that in contrast to the normal paths which calculate a path from a specific point to another specific point, calculates a random path away from a starting point.

RandomPath path = RandomPath.Construct(transform.position, searchLength);
path.spread = spread;
seeker.StartPath(path);
See Also
Searching for paths

Adding this to any of the included movement scripts does however require that you create a new class that inherits from that movement script and overrides the relevant methods. So the other methods may be easier if you are using those.

Advantages

  • Picks a point and calculates a path in one go.
  • Every node that is considered has the same probability of being chosen, no bias towards being near obstacles like in Method 1: Random point inside a circle.
  • A minimum path cost can be set (searchLength).

Disadvantages

  • Can be slow for long paths.
  • Not as easy to integrate with the built-in movement scripts.
  • Does not work that well for navmesh/recast graphs as every node has the same probability of being chosen, which will cause a bias towards regions with a lot of detail (and thus more and smaller nodes).

Misc

  • Takes penalties into account.
See Also
Pathfinding.RandomPath

Method 3: The ConstantPath type

The ConstantPath type is a path type which will find all nodes which can be reached from the start point with a cost at most equal to a particular value. After all those nodes have been found we can pick one or more random points on the surface of those nodes.

ConstantPath path = ConstantPath.Construct(transform.position, searchLength);
path.BlockUntilCalculated();
var singleRandomPoint = PathUtilities.GetPointsOnNodes(path.allNodes, 1)[0];
var multipleRandomPoints = PathUtilities.GetPointsOnNodes(path.allNodes, 100);

If you want to feed this to a built-in movement script you can use the same approach as in Method 1: Random point inside a circle.

See Also
Pathfinding.ConstantPath
Pathfinding.PathUtilities.GetPointsOnNodes

Advantages

  • Can pick multiple random points with just a single path request.
  • The probability of chosing a node is proportional to its surface area (so if all nodes have the same size, e.g when using a grid graph then every node that is considered has the same probability of being chosen). There is no bias towards being near obstacles like in Method 1: Random point inside a circle.
  • Possible to do custom filtering of the nodes afterwards if that should be necessary.
  • Usually slightly faster than Method 2: The RandomPath type.
  • Works reasonably well for navmesh/recast graphs.

Disadvantages

  • Can be slow when having to search a lot of nodes.

Misc

  • Takes penalties into account.

Method 4: Breadth-first search

A breadth-first search is a simple search that searches outwards from the starting node a single node at a time. It doesn't take penalties or any other types of costs into account. This means for example that moving diagonally on a grid graph has the same cost as moving along one of the 4 non-diagonal connections.

The way you use it is very similar to what is done in Method 3: The ConstantPath type.

var startNode = AstarPath.active.GetNearest(transform.position).node;
var nodes = PathUtilities.BFS(startNode, nodeDistance);
var singleRandomPoint = PathUtilities.GetPointsOnNodes(nodes, 1)[0];
var multipleRandomPoints = PathUtilities.GetPointsOnNodes(nodes, 100);

If you want to feed this to a built-in movement script you can use the same approach as in Method 1: Random point inside a circle.

See Also
Pathfinding.PathUtilities.BFS
Pathfinding.PathUtilities.GetPointsOnNodes

Advantages

  • Can pick multiple random points, not just one.
  • The probability of chosing a node is proportional to its surface area (so if all nodes have the same size, e.g when using a grid graph then every node that is considered has the same probability of being chosen). There is no bias towards being near obstacles like in Method 1: Random point inside a circle.
  • Possible to do custom filtering of the nodes afterwards if that should be necessary.
  • No round trip to the pathfinding system necessary which can save some overhead.
  • Usually slightly faster than Method 3: The ConstantPath type and Method 2: The RandomPath type.

Disadvantages

  • Can be slow when having to search a lot of nodes.
  • Does not use the pathfinding threads, so you loose the ability to easily offload it from the main Unity thead.
  • Does not work particularly well for navmesh/recast graphs as the paths will have a large variation in length depending on the detail of the navmesh (more and smaller nodes means the BFS will not reach as far).

Misc

  • Does not take penalties or any other costs into account, only the number of nodes traversed is relevant.