menu_bookDocumentation
NavMeshAgent: MoveTo, WishVelocity Pattern, Off-Mesh Links, Area Constraints, and Path Queries
NavMeshAgent: Navigation, WishVelocity, Links, and Path Control
NavMeshAgent is the s&box component for AI navigation using the scene's navmesh. It uses DotRecast (Detour/Crowd) internally and integrates with the NavMeshAgentSystem for crowd simulation.Basic Usage
CSHARP
var agent = GetComponent<NavMeshAgent>();
// Navigate to a position
agent.MoveTo( targetPosition );
// Stop navigation
agent.Stop();
// Check if navigating
if ( agent.IsNavigating )
{
// Use WishVelocity to drive a PlayerController
controller.WishVelocity = agent.WishVelocity;
}WishVelocity Pattern
The most common pattern is to use WishVelocity to drive a PlayerController. WishVelocity is the crowd-computed desired velocity — it already accounts for obstacle avoidance and separation from other agents.
CSHARP
protected override void OnFixedUpdate()
{
if ( IsProxy ) return;
agent.MoveTo( targetPosition );
if ( agent.IsNavigating )
{
controller.WishVelocity = agent.WishVelocity;
}
else
{
controller.WishVelocity = Vector3.Zero;
}
}Key Properties
CSHARP
agent.Height = 64f; // agent capsule height
agent.Radius = 16f; // agent capsule radius
agent.MaxSpeed = 120f; // maximum movement speed
agent.Acceleration = 120f; // how fast velocity changes (snappy = high value)
agent.Separation = 0.25f; // crowd separation strength [0..1]
agent.UpdatePosition = true; // auto-update GameObject position
agent.UpdateRotation = false; // auto-rotate toward movement direction
agent.AutoTraverseLinks = true; // auto-traverse off-mesh links
agent.AgentPosition // current agent position (even if UpdatePosition = false)
agent.TargetPosition // current target position (null if not navigating)
agent.Velocity // current velocity
agent.WishVelocity // desired velocity (use this to drive movement)Off-Mesh Links
When AutoTraverseLinks = false, you handle link traversal yourself (e.g., for jumping or climbing):
CSHARP
agent.AutoTraverseLinks = false;
agent.LinkEnter = () =>
{
var data = agent.CurrentLinkTraversal.Value;
// data.LinkEnterPosition, data.LinkExitPosition, data.LinkComponent
StartJump( data.LinkEnterPosition, data.LinkExitPosition );
};
agent.LinkExit = () => { /* link traversal complete */ };
// When done traversing:
agent.CompleteLinkTraversal();Area Constraints
CSHARP
// Only allow specific areas
agent.AllowedAreas.Add( myNavMeshArea );
// Forbid specific areas
agent.ForbiddenAreas.Add( dangerArea );
// Allow/disallow the default area
agent.AllowDefaultArea = true;Path Queries
CSHARP
// Get current path (not free — avoid calling every frame)
var path = agent.GetPath();
if ( path.Status == NavMeshPathStatus.Complete )
{
foreach ( var point in path.Points )
Log.Info( point.Position );
}
// Look-ahead position (for rotation)
var lookTarget = agent.GetLookAhead( 30f );
Was this helpful?