Quick answer: Only move the agent using the velocity from the velocity_computed signal. Tune time_horizon up and max_neighbors down to smooth crowding.

A crowd of NavigationAgent3D NPCs jitter back and forth when they cluster. They’re applying both desired and avoidance velocity, fighting each other.

Correct Avoidance Flow

func _physics_process(delta):
    var next = nav_agent.get_next_path_position()
    var desired = (next - global_position).normalized() * speed
    nav_agent.velocity = desired   # feed desired into avoidance

func _on_velocity_computed(safe_velocity):
    velocity = safe_velocity        # apply ONLY the safe velocity
    move_and_slide()

Set desired velocity into the agent; the avoidance system returns safe_velocity via signal; apply that. Don’t apply desired directly.

Tune Parameters

Avoidance Priority

Set avoidance_priority so important agents (player-followers) push through, decoration NPCs yield. Reduces deadlock jitter.

Verifying

Spawn 50 agents converging on one point. They flow around each other smoothly, no vibration. Profiler shows avoidance cost within budget.

“Feed desired in, apply safe out. Mixing the two causes the fight that looks like jitter.”

For RTS-scale crowds (hundreds of units), consider flow-field pathfinding instead — per-agent RVO doesn’t scale past a few hundred.