Unity Navigation (NavMesh, Pathfinding, AI)
Overview
Unity's AI Navigation package (com.unity.ai.navigation) bakes a
NavMesh -- a simplified walkable surface -- and provides
NavMeshAgent to move characters along it. This is the standard solution
for AI NPCs in the generated project.
Baking a NavMesh
- Mark static colliders as Navigation Static (Window > AI > Navigation > Object).
- Bake the NavMesh (Window > AI > Navigation > Bake).
- At runtime, every
NavMeshAgenton the scene automatically walks on the baked NavMesh.
For a procedurally generated city, baking at design time is impossible. Either:
- Bake at runtime via
NavMeshSurface.BuildNavMesh()(AI Navigation package), or- Use the simpler approach in
NPCController.cs: pick random points viaNavMesh.SamplePositionso the agent always lands on a valid walkable spot.
NavMeshAgent
[RequireComponent(typeof(NavMeshAgent))]
public class NPCController : MonoBehaviour
{
private NavMeshAgent _agent;
private void Awake() => _agent = GetComponent<NavMeshAgent>();
private void Start()
{
PickNewDestination();
}
private void PickNewDestination()
{
Vector3 random = transform.position + Random.insideUnitSphere * 20f;
if (NavMesh.SamplePosition(random, out NavMeshHit hit, 20f, NavMesh.AllAreas))
_agent.SetDestination(hit.position);
}
}
Key properties:
| Property | Meaning |
|---|---|
speed |
Max movement speed (m/s) |
angularSpeed |
Max turning speed (deg/s) |
acceleration |
How quickly the agent reaches speed |
stoppingDistance |
Distance at which the agent considers the destination reached |
autoBraking |
Whether to slow down near the destination |
isStopped |
Pause the agent without clearing the path |
remainingDistance |
Distance to the end of the current path |
pathPending |
True while a new path is still being computed |
State machines for AI
A common pattern is a small finite state machine:
Idle --(timer)--> Wander --(player in range)--> Chase
^ | |
| (lost sight) +---------------------------------+
+--------------------+
The generated NPCController.cs implements exactly this pattern with three
states (Idle, Wander, Chase) and switch-based dispatch in Update().
Pathfinding details
NavMeshAgent.SetDestination(target)is async -- the path may not be ready on the same frame. Check!agent.pathPendingbefore readingremainingDistance.agent.pathStatustells you whether a path isPathComplete,PathPartialorPathInvalid.NavMesh.CalculatePath(source, target, mask, out path)lets you compute a path without an agent (useful for "can the NPC reach this point?" checks).
NavMeshObstacle
For dynamic obstacles (a car parked across a road, a door that closes), add
a NavMeshObstacle component. Set carve = true to actually cut a hole in
the NavMesh; otherwise the obstacle only pushes agents around.
Off-mesh links
When the walkable surface is disconnected (e.g. a gap between rooftops),
drop an OffMeshLink to let agents jump or teleport across. You can also
use them for ladders, climbing walls, and jumping down from ledges.
Performance
- Keep the agent count under ~100 simultaneous active agents on desktop.
- For larger crowds use the ECS/DOTS navigation solutions or batch pathfinding across frames.
- Set
agent.autoRepath = falseif you do not need the agent to follow moving targets, and callSetDestinationless often (e.g. every 0.5 s).