Skip to main content
The navigation system is built on Recast/Detour and uses a crowd simulation model so multiple agents avoid each other automatically. Three components drive the system:
  • NavMeshAgent — attaches to an NPC or entity and navigates to targets.
  • NavMeshArea — marks a volume in the scene as blocked or as a custom area type.
  • NavMeshLink — creates an off-mesh connection between two points, enabling jumps, ladders, or teleports.
The NavMesh itself is baked per-scene. Place NavMeshArea and NavMeshLink components before baking, or mark them as dynamic so changes are applied at runtime.

NavMeshAgent navigates an entity across the scene’s NavMesh. Attach it to a GameObject and call MoveTo to start pathfinding. The agent integrates into the crowd system and avoids other agents automatically.

Physical properties

Height
float
default:"64"
The height of the agent’s collision cylinder. Should match the character’s CharacterController height.
Radius
float
default:"16"
The radius of the agent’s collision cylinder. Should match the character’s CharacterController radius.

Movement properties

MaxSpeed
float
default:"120"
Maximum movement speed in world units per second.
Acceleration
float
default:"120"
Maximum rate of velocity change in world units per second squared. Set this equal to or higher than MaxSpeed for snappy, responsive movement.
UpdatePosition
bool
default:"true"
When true, the component writes the agent’s NavMesh position back to the GameObject’s world position each frame. Set to false to take manual control of positioning using AgentPosition.
UpdateRotation
bool
default:"false"
When true, the GameObject automatically faces the direction of travel. Turn this off if you handle rotation yourself.

Constraints

AllowedAreas
HashSet<NavMeshAreaDefinition>
The set of area types the agent is permitted to traverse. If empty, all areas are allowed.
ForbiddenAreas
HashSet<NavMeshAreaDefinition>
The set of area types the agent is not permitted to traverse. If empty, no areas are forbidden.
AllowDefaultArea
bool
default:"true"
Whether the agent can travel on the default (untyped) NavMesh area.
When true, the agent traverses NavMeshLink connections automatically. Set to false to handle link traversal yourself using CompleteLinkTraversal().
Separation
float
default:"0.25"
How strongly the agent avoids other agents in the crowd. Range 0–1.

State

Velocity
Vector3
The agent’s current velocity as reported by the crowd simulation.
WishVelocity
Vector3
The velocity the agent wants to move at this frame. Pass this into a CharacterController to combine navigation with physics-based movement.
IsNavigating
bool
true when the agent has a valid path target and is actively moving toward it.
AgentPosition
Vector3
The agent’s position on the NavMesh. Updated even when UpdatePosition is false.
TargetPosition
Vector3?
The current navigation target, or null if the agent is not navigating.
true while the agent is crossing a NavMeshLink.

Methods

MethodDescription
MoveTo(Vector3 targetPosition)Requests a path to targetPosition and starts navigating. Spam-safe — duplicate calls for the same destination are ignored.
Stop()Cancels the current navigation target and stops the agent.
SetAgentPosition(Vector3 position)Teleports the agent to a new position on the NavMesh.
SetPath(NavMeshPath path)Assigns a pre-calculated path for the agent to follow.
GetPath()Returns the agent’s current path as a NavMeshPath. Avoid calling every frame.
GetLookAhead(float distance)Returns a point on the current path distance units ahead of the agent. Useful for smooth rotation.
CompleteLinkTraversal()Signals that a manual link traversal is complete. Only needed when AutoTraverseLinks is false.

Events

Fired when the agent begins traversing a NavMeshLink.
Fired when the agent finishes traversing a NavMeshLink.

NavMeshArea defines a volume that modifies NavMesh generation. Use it to block off rooms, mark hazardous zones, or tag areas with custom area types so agents can filter them.
IsBlocker
bool
default:"true"
When true, NavMesh generation is completely disabled inside this volume. No agent can path through it.
Area
NavMeshAreaDefinition
The area type to apply to the volume. Agents can allow or forbid specific area types via AllowedAreas / ForbiddenAreas. Ignored when IsBlocker is true.
NavMeshArea extends VolumeComponent. The volume’s shape is defined by the scene volume geometry attached to the same GameObject.
Static NavMeshArea components (not moved at runtime) have near-zero performance cost. Moving them dynamically triggers a NavMesh rebuild for the affected tiles, so limit runtime movement to when it is truly necessary.

NavMeshLink creates an off-mesh connection between two points, letting agents path through gaps that the baked mesh does not bridge — for example a ladder, a jump pad, or a doorway.
LocalStartPosition
Vector3
Start point of the link, relative to the GameObject’s origin.
LocalEndPosition
Vector3
End point of the link, relative to the GameObject’s origin.
IsBiDirectional
bool
default:"true"
When true, agents can traverse the link in both directions. When false, traversal is only allowed from start to end.
ConnectionRadius
float
default:"16"
Search radius used at each end to find the nearest NavMesh polygon to connect to.
Area
NavMeshAreaDefinition
The area type assigned to this link. Agents that have this area in their ForbiddenAreas will not use the link.
WorldStartPositionOnNavmesh
Vector3?
The start endpoint snapped to the nearest NavMesh polygon. null if the start is not connected.
WorldEndPositionOnNavmesh
Vector3?
The end endpoint snapped to the nearest NavMesh polygon. null if the end is not connected.

Events

Fired when an agent enters this link.
Fired when an agent exits this link.
If ConnectionRadius is too small the link endpoints may not snap to the NavMesh. Check WorldStartPositionOnNavmesh and WorldEndPositionOnNavmesh to verify the link is connected — they return null when the snap fails.

Example: simple NPC follower

The following component makes an NPC continuously follow the player. It combines NavMeshAgent with CharacterController so the agent’s wish velocity feeds into physics-aware movement.
using Sandbox;

public sealed class NpcFollower : Component
{
    [Property] public GameObject Target { get; set; }
    [Property] public float StopDistance { get; set; } = 80f;

    NavMeshAgent _agent;
    CharacterController _cc;

    protected override void OnStart()
    {
        _agent = Components.Get<NavMeshAgent>();
        _cc    = Components.Get<CharacterController>();

        // We drive position ourselves via CharacterController
        _agent.UpdatePosition = false;
        _agent.UpdateRotation = false;
    }

    protected override void OnFixedUpdate()
    {
        if ( _agent is null || Target is null ) return;

        var distToTarget = WorldPosition.Distance( Target.WorldPosition );

        if ( distToTarget > StopDistance )
        {
            _agent.MoveTo( Target.WorldPosition );
        }
        else
        {
            _agent.Stop();
        }

        if ( _cc is not null )
        {
            // Feed the NavMesh wish velocity into the character controller
            _cc.Velocity = _cc.Velocity.WithZ( _cc.Velocity.z );
            _cc.Accelerate( _agent.WishVelocity );

            // Apply gravity
            if ( !_cc.IsOnGround )
                _cc.Velocity -= Vector3.Up * 800f * Time.Delta;

            _cc.Move();

            // Tell the agent where we ended up after collision resolution
            _agent.SetAgentPosition( WorldPosition );
        }

        // Smoothly face the direction of travel
        if ( _agent.WishVelocity.LengthSquared > 1f )
        {
            var targetRot = Rotation.LookAt( _agent.WishVelocity.Normal.WithZ( 0 ) );
            WorldRotation = Rotation.Slerp( WorldRotation, targetRot, Time.Delta * 8f );
        }
    }
}
Set UpdatePosition to false and manage position via CharacterController when your NPC needs proper collision against the world geometry. Use SetAgentPosition after each move to keep the crowd simulation in sync.

Build docs developers (and LLMs) love