Quick answer: Agents cannot reach positions within Agent Radius of a NavMesh edge. Use NavMesh.SamplePosition(target, out hit, maxDistance, NavMesh.AllAreas) to snap destinations to valid points, and tune the bake Agent Radius to match your actual agent size.

Here is how to fix Unity NavMeshAgent stuck on edge. You call agent.SetDestination(playerPosition). The enemy runs toward the player, hits a wall, and stops. Or it stops a foot short of the doorway. Or it oscillates between two positions at the edge of the navmesh, never reaching its target. NavMeshAgents are reliable when the destination is valid and fall apart quietly when it is not.

The Symptom

A NavMeshAgent stops short of its target or gets stuck at a NavMesh edge. agent.remainingDistance stays above zero forever. agent.hasPath returns true but the agent does not move. agent.pathStatus returns Partial or Invalid.

Variants: agent stops at wall corners, cannot enter narrow doorways, jitters at off-mesh link endpoints, or walks in circles around a single point.

What Causes This

Destination off the NavMesh. SetDestination with a position that is not on the NavMesh returns partial paths. The agent walks to the nearest reachable point, which may be far from the actual target. agent.pathStatus == NavMeshPathStatus.PathPartial confirms this.

Agent Radius bake vs runtime mismatch. The NavMesh bake’s Agent Radius inflates the reachable area away from obstacles. An agent component with radius 0.5 on a NavMesh baked with radius 0.5 has no extra clearance. Narrow passages get carved out of the navmesh even though an agent could physically fit.

Step Height too small. If the NavMesh bake’s Step Height is smaller than actual world steps, the NavMesh has gaps at staircases. Agents reach the edge and stop.

Dynamic obstacles with carving. A NavMeshObstacle with Carve enabled modifies the NavMesh in real-time. If the obstacle appears on the agent’s path, the agent may find no path or a partial one. Carving has latency; frequent carving obstacles produce jittery agent behavior.

Off-mesh link endpoints imprecise. Off-mesh links define manual connections (jumps, ladders). If their start/end points are not exactly on the navmesh, the agent can oscillate at entry/exit as it switches between mesh and link traversal.

The Fix

Step 1: Sample destinations before setting.

using UnityEngine;
using UnityEngine.AI;

public class EnemyChase : MonoBehaviour
{
    [SerializeField] private Transform target;
    private NavMeshAgent agent;

    void Awake() { agent = GetComponent<NavMeshAgent>(); }

    void Update()
    {
        Vector3 dest = target.position;
        if (NavMesh.SamplePosition(dest, out NavMeshHit hit, 5f, NavMesh.AllAreas))
        {
            agent.SetDestination(hit.position);
        }
    }
}

SamplePosition finds the closest valid navmesh position within a radius. Agent now always has a reachable destination, even if the target steps off the mesh.

Step 2: Tune Agent Radius and Step Height in Bake settings. Open Window > AI > Navigation > Bake tab:

Re-bake after changes. Small adjustments to Radius or Step Height open or close narrow passages.

Step 3: Use multi-agent bakes if you have different sizes. For a project with small rats and large ogres, bake two NavMeshes with different Agent Radius values. Assign each agent to its appropriate mesh via the Agent Type property. One bake cannot serve agents of wildly different sizes well.

Step 4: Guard against incomplete paths. Check pathStatus and react:

if (agent.hasPath && agent.pathStatus == NavMeshPathStatus.PathPartial)
{
    Debug.LogWarning("Path to target is partial — destination may be unreachable");
    // fallback behavior: wait, retry, find alternate target
}

Partial paths are a design signal that something is wrong — destination off mesh, blocked by dynamic obstacle, or mesh gap. Log and handle; do not pretend the agent is pathfinding correctly.

Off-Mesh Link Troubleshooting

If agents jitter at off-mesh links, verify:

  1. Start and End transforms of the link are positioned exactly on the NavMesh (use SamplePosition to snap them in editor)
  2. The link’s Bidirectional checkbox matches your intent
  3. Agent’s Auto Traverse Off Mesh Link is true
  4. No collider blocks the direct line of the link

For manual traversal (custom jump animations), set Auto Traverse to false and handle agent.isOnOffMeshLink in code — call agent.CompleteOffMeshLink when the custom animation finishes.

Debugging with AI Navigation

Open Scene view > right-click Gizmos > enable “Show NavMesh.” Blue areas are walkable. Gaps in your walkable surface at doorways or ramps indicate bake settings that exclude them. Agents cannot cross those gaps.

“Agents only pathfind on the NavMesh. If the bake is wrong, no amount of SetDestination will fix it.”

Related Issues

For general NavMeshAgent issues, see NavMeshAgent Not Moving. For bake failures, NavMesh Building Fails on High-Poly Mesh covers bake-time issues.

SamplePosition before SetDestination. Re-bake after settings changes. Check pathStatus.