You have a player that walks, jumps, pushes crates, and animates smoothly using everything covered earlier in this series. Now your level needs something that moves on its own — an enemy that chases the player, a guard that patrols a route, or an NPC that walks to a specific point and waits. Writing that pathfinding logic by hand, avoiding every wall and obstacle, would take an enormous amount of work. That is exactly what Unity's NavMesh system solves for you automatically.
This guide starts from zero: what a NavMesh actually is, how to bake one for your level, how the NavMeshAgent component moves a character along it, and how to build a working chase-and-patrol enemy with animation blending tied into the Animator system from our earlier guide.
What Is a NavMesh in Unity?
A NavMesh (short for Navigation Mesh) is a simplified representation of the walkable surfaces in your level — floors, ramps, platforms — that Unity generates automatically through a process called baking. Once baked, this mesh tells Unity exactly where characters are allowed to walk, letting it calculate paths around walls, obstacles, and gaps without you writing any pathfinding code yourself.
The NavMesh itself is invisible during normal gameplay; it exists purely as data Unity uses internally for pathfinding. You only see it as a highlighted blue overlay inside the Unity Editor's Navigation window, never in the actual built game.
What Is a NavMeshAgent?
A NavMeshAgent is the component you attach to any character that needs to move along the NavMesh. Once you give it a destination, the NavMeshAgent automatically calculates the shortest valid path, moves the character along it, and steers around both static level geometry and other dynamic obstacles — all without you writing the underlying pathfinding math.
This is conceptually similar to giving someone a GPS destination instead of telling them exactly which streets to turn down — you say "go here," and the system figures out the route.
Why NavMesh Matters
A common mistake beginners make when first building enemy AI is writing simple "always move toward the player" code using basic Vector3 math. This works in a completely open, empty room, but the moment a wall or pillar exists between the enemy and the player, that approach breaks down — the enemy walks straight into the wall and gets stuck, with no idea how to go around it.
NavMesh solves exactly this problem. It understands the actual layout of your level, including walls, ramps, and gaps, and calculates a path that intelligently avoids obstacles, which would otherwise require a substantial amount of custom pathfinding code (like implementing A* search yourself) to replicate.
When To Use NavMesh
- Enemies that need to chase or hunt the player through complex level geometry.
- NPCs that patrol a fixed route between several points.
- Characters that need to walk to a specific location and stop, like an NPC walking to a chair and sitting down.
- Crowd or group movement, where multiple agents need to navigate the same space without all colliding into each other at once.
When Not To Use NavMesh
- For your player character — NavMesh is designed for AI-controlled movement, not direct player input. Continue using Character Controller or Rigidbody, as covered in our earlier guides, for the player.
- For simple, fixed-path movement that never needs to react to obstacles, like an elevator moving between two exact points — a basic scripted Transform or Rigidbody movement is simpler and more precise for that case.
- For very small, simple levels with no obstacles at all between the AI and its target, where direct movement may be sufficient and baking a NavMesh would be unnecessary overhead.
- For physics-driven characters that need to be affected by forces and momentum in complex ways — NavMeshAgent handles its own movement directly and does not interact with the physics engine the same way Rigidbody does.
This part usually confuses new users: NavMeshAgent and Character Controller solve similar-sounding problems (moving a character around a level) but for very different audiences — NavMeshAgent is built for AI making its own movement decisions, while Character Controller is built for direct, frame-by-frame player input.
Advantages of NavMesh
| Advantage | Why It Helps |
| Automatic obstacle avoidance | Agents intelligently path around walls and obstacles without any custom pathfinding code. |
| Built into Unity | No additional packages or plugins are required for basic NavMesh functionality. |
| Handles complex level geometry | Works correctly across ramps, multiple floors, and irregularly shaped rooms once properly baked. |
| Dynamic re-routing | If a path becomes blocked by a NavMesh Obstacle, agents automatically recalculate a new route. |
Disadvantages of NavMesh
| Disadvantage | Why It Matters |
| Requires baking | Any significant change to level geometry requires re-baking the NavMesh, which is easy to forget during development. |
| Less precise than scripted movement | Fine-grained control over exact movement feel is more limited compared to a custom Character Controller or Rigidbody script. |
| Performance cost with many agents | A large number of simultaneously pathfinding agents adds CPU cost, which matters more on mobile, per our Mobile Optimization guide. |
| Static by default | The baked mesh does not automatically update for moving doors or destructible walls without additional NavMesh Obstacle setup. |
Project Setup
Installing the AI Navigation Package
In recent Unity versions, NavMesh baking tools live in a separate package rather than being built into the core engine by default.
- Open Window > Package Manager.
- Switch the dropdown to Unity Registry.
- Search for AI Navigation and click Install.
Recommended Folder Structure
- Assets/Scripts — the EnemyChase and EnemyPatrol scripts from this guide.
- Assets/Prefabs — save your finished enemy character here once working.
Baking Your First NavMesh
Step 1: Mark Your Geometry as Navigation Static
- Select your floor, walls, and any other level geometry that should affect walkability.
- In the top-right of the Inspector, click the Static dropdown next to the Static checkbox, and ensure Navigation Static is checked.
Step 2: Add a NavMesh Surface
- In the Hierarchy, right-click and choose AI > NavMesh Surface (or add the NavMeshSurface component to an existing empty GameObject).
- Select the NavMesh Surface object, and in the Inspector, click Bake.
You will see a blue overlay appear on your floor in the Scene view, representing every area Unity has calculated as walkable. If a section of your floor does not turn blue, double-check that it was marked Navigation Static before baking, or that nothing is blocking it from above (like an invisible collider sitting just above the floor).
Understanding Key Bake Settings
| Setting | What It Does | Typical Beginner Setting |
| Agent Radius | How wide the agent is considered to be, used to keep paths away from walls by this distance. | 0.5 (default, fine for most humanoid characters) |
| Agent Height | How tall the agent is considered to be, affecting which low ceilings or gaps it can pass under. | 2 (default, fine for most humanoid characters) |
| Max Slope | The steepest ramp angle the agent can walk up, similar in concept to Character Controller's Slope Limit. | 45 degrees |
| Step Height | The maximum height of a step or ledge the agent can climb without it being treated as an obstacle. | 0.4 (similar to Character Controller's Step Offset) |
A quick rule of thumb: if your enemy character and player character are roughly the same size, you can use very similar values here to the Character Controller settings from our earlier guide, since both are describing the same physical space the character needs to move through.
Adding a NavMeshAgent
- Create or select your enemy character GameObject.
- Click Add Component and search for Nav Mesh Agent.
- Leave the default settings for now — we will tune Speed and Stopping Distance shortly.
Understanding Each Property
| Property | What It Does | Typical Beginner Setting |
| Speed | How fast the agent moves, in units per second. | 3.5 (a typical walking pace) |
| Angular Speed | How quickly the agent rotates to face its movement direction, in degrees per second. | 120 |
| Acceleration | How quickly the agent speeds up or slows down. | 8 |
| Stopping Distance | How close the agent gets to its destination before considering itself "arrived." | 0.5 - 1.5, depending on the situation |
| Auto Braking | When enabled, the agent slows down smoothly as it approaches its destination instead of stopping abruptly. | Checked, for natural-feeling stops |
Writing Your First Script: Chasing the Player
Let's build the simplest and most common NavMesh use case: an enemy that constantly moves toward the player.
using UnityEngine;
using UnityEngine.AI;
public class EnemyChase : MonoBehaviour
{
public Transform target;
private NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if (target != null)
{
agent.SetDestination(target.position);
}
}
}
Attach this script to your enemy, and drag your Player object into the Target field in the Inspector. Press Play — the enemy will now automatically walk toward the player, navigating around any walls or obstacles in between.
Line By Line Explanation
public Transform target; is a reference to whatever the enemy should chase — typically the player's Transform, assigned directly in the Inspector for simplicity in this beginner example.
agent = GetComponent<NavMeshAgent>(); caches the NavMeshAgent reference once in Start(), following the same caching pattern used throughout this series.
agent.SetDestination(target.position); is the entire pathfinding instruction. This single line tells Unity "calculate a path to this position and move there," and the NavMeshAgent handles literally everything else — pathing around obstacles, accelerating, rotating to face the movement direction, and avoiding other agents.
Calling SetDestination() every frame in Update() is intentional here, since the player is constantly moving and the enemy needs to continuously recalculate its path toward the player's current position rather than a single fixed point.
A Real Example: Building a Patrol Route
Let's look at a simple example of the second most common NavMesh pattern: an NPC or enemy that moves between a set of fixed waypoints rather than chasing a moving target.
using UnityEngine;
using UnityEngine.AI;
public class EnemyPatrol : MonoBehaviour
{
public Transform[] waypoints;
public float waitTimeAtPoint = 2f;
private NavMeshAgent agent;
private int currentWaypointIndex = 0;
private float waitTimer = 0f;
private bool isWaiting = false;
void Start()
{
agent = GetComponent<NavMeshAgent>();
GoToNextWaypoint();
}
void Update()
{
if (isWaiting)
{
waitTimer += Time.deltaTime;
if (waitTimer >= waitTimeAtPoint)
{
isWaiting = false;
waitTimer = 0f;
GoToNextWaypoint();
}
return;
}
if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance)
{
isWaiting = true;
}
}
void GoToNextWaypoint()
{
if (waypoints.Length == 0)
{
return;
}
agent.SetDestination(waypoints[currentWaypointIndex].position);
currentWaypointIndex = (currentWaypointIndex + 1) % waypoints.Length;
}
}
Create several empty GameObjects in your scene to act as waypoints, drag them into the Waypoints array on this script in order, and attach it to your enemy alongside a NavMeshAgent. The enemy will now walk to each point in sequence, pause briefly, and continue to the next one in a loop.
Key Lines Explained
agent.pathPending is true while Unity is still calculating a path and has not finished yet. Checking this prevents your script from thinking the agent has "arrived" during the brief moment the path is still being computed.
agent.remainingDistance <= agent.stoppingDistance checks whether the agent is close enough to its current destination to be considered arrived, using the Stopping Distance value set on the NavMeshAgent component itself.
currentWaypointIndex = (currentWaypointIndex + 1) % waypoints.Length; advances to the next waypoint in the array, and the modulo operator (%) wraps back around to the first waypoint once the last one is reached, creating a continuous loop.
Connecting NavMesh to the Animator
Since you already built an Animator-driven character in our earlier guide, here is how to drive the same Speed parameter using a NavMeshAgent instead of a Character Controller.
using UnityEngine;
using UnityEngine.AI;
public class NavMeshAnimatorBridge : MonoBehaviour
{
private NavMeshAgent agent;
private Animator animator;
void Start()
{
agent = GetComponent<NavMeshAgent>();
animator = GetComponent<Animator>();
}
void Update()
{
float normalizedSpeed = agent.velocity.magnitude / agent.speed;
animator.SetFloat("Speed", normalizedSpeed);
}
}
agent.velocity gives the agent's current actual movement speed, which can be lower than its maximum Speed setting while accelerating, decelerating, or turning. Dividing by agent.speed normalizes this into a roughly 0-to-1 range, which works well as input for the same Blend Tree built in our Animator guide, without needing two different Speed calculation systems for player and enemy characters.
Beginner Mistakes
- Forgetting to mark level geometry as Navigation Static before baking. Unmarked geometry is invisible to the bake process, leaving floors un-walkable even though they look fine visually.
- Forgetting to re-bake after changing the level. The NavMesh is a snapshot taken at bake time — moving walls or adding new geometry afterward has no effect until you bake again.
- Setting transform.position directly on a NavMeshAgent-controlled character. This can desynchronize the agent from its internal pathfinding state. Use Warp() instead if you need to instantly teleport an agent.
- Calling SetDestination() every single frame for a patrol script. Unlike chasing a moving player, a patrol destination is fixed — recalculating it constantly wastes CPU cycles for no benefit; only call it once when starting a new leg of the patrol.
- Not accounting for agent.pathPending. Checking remainingDistance before the path has finished calculating can cause false "arrived" detections, especially right after SetDestination() is called.
- Adding a NavMeshAgent and a Rigidbody to the same object without understanding the interaction. NavMeshAgent handles its own movement and does not need a Rigidbody for basic functionality; combining them without care can cause conflicting movement behavior.
- Forgetting to add a NavMesh Obstacle to dynamic objects like doors or movable crates. Without this, agents will not know to path around objects that move during gameplay.
Troubleshooting Guide
Problem: My agent does not move at all.
Likely cause: The NavMesh was never baked, the floor was not marked Navigation Static, or the agent's starting position is not actually on the baked NavMesh surface.
Fix: Confirm the blue NavMesh overlay is visible on your floor in the Scene view. Check that the agent spawns on or very near that blue area, not floating above it or embedded inside a wall.
Problem: I get a "Failed to create agent" or similar warning in the console.
Likely cause: The agent's spawn position is too far from any baked NavMesh surface for Unity to place it correctly.
Fix: Move the agent's starting position closer to or directly onto the blue NavMesh area, or increase the NavMesh Surface's bake settings to cover the intended spawn area.
Problem: My enemy walks straight through a wall instead of going around it.
Likely cause: The wall was not marked Navigation Static before baking, so it was never factored into the NavMesh calculation.
Fix: Select the wall, mark it Navigation Static, and re-bake the NavMesh Surface.
Problem: My patrol script thinks the agent has arrived immediately, before it actually moves.
Likely cause: remainingDistance is being checked before pathPending has finished, so it briefly reads an old or zero value right after SetDestination() is called.
Fix: Always check !agent.pathPending alongside the remainingDistance comparison, as shown in the EnemyPatrol script in this guide.
Problem: My enemy's animation does not match its movement speed.
Likely cause: The Animator's Speed parameter is being driven by agent.speed (the maximum configured speed) instead of agent.velocity.magnitude (the actual current speed).
Fix: Use agent.velocity.magnitude divided by agent.speed, as shown in the NavMeshAnimatorBridge script, so the animation reflects real-time acceleration and deceleration.
Problem: Multiple agents pile up and push through each other at a doorway.
Likely cause: Avoidance settings, or the Agent Radius set during baking, may be too small relative to the actual space available for multiple agents to pass through comfortably.
Fix: Adjust the NavMeshAgent's Quality / Avoidance settings, or widen narrow passages in your level geometry if many agents are expected to pass through the same area simultaneously.
Best Practices
- Always mark relevant level geometry as Navigation Static before baking, and remember to re-bake after any layout changes.
- Use NavMesh Obstacle components on dynamic objects like doors or movable crates so agents correctly path around them at runtime.
- Only call SetDestination() when the target actually needs to change — every frame for a moving chase target, but only once per waypoint for fixed patrol points.
- Always check !agent.pathPending before relying on remainingDistance, to avoid false "arrived" detections.
- Drive Animator parameters using agent.velocity.magnitude rather than the configured maximum Speed, for animation that reflects real acceleration and deceleration.
- Keep Agent Radius and Height values consistent with your actual character size, similar to tuning Character Controller's Radius and Height from our earlier guide.
- Limit the number of simultaneously active pathfinding agents in performance-sensitive scenes, especially on mobile, per our Mobile Optimization guide.
Frequently Asked Questions
What is a NavMesh in Unity?
A NavMesh is a simplified representation of the walkable surfaces in a level, generated through a baking process, which Unity uses to calculate paths for AI-controlled characters around obstacles automatically.
What is a NavMeshAgent?
It is a component attached to an AI-controlled character that moves it along a baked NavMesh toward a given destination, automatically handling pathfinding, obstacle avoidance, and movement.
What is the difference between NavMeshAgent and Character Controller?
NavMeshAgent is designed for AI-controlled characters that calculate their own paths toward a destination automatically, while Character Controller is designed for direct, frame-by-frame player input where you script every movement decision yourself.
How do I bake a NavMesh in Unity?
Mark your level geometry as Navigation Static, add a NavMesh Surface component to a GameObject (after installing the AI Navigation package), and click Bake in its Inspector.
Why does my NavMeshAgent not move?
The most common causes are the NavMesh never having been baked, the floor not being marked Navigation Static, or the agent's spawn position being too far from the actual baked NavMesh surface.
Why does my enemy walk through walls instead of around them?
The wall geometry was likely not marked Navigation Static before the NavMesh was baked, so it was never accounted for in the pathfinding calculation. Mark it and re-bake.
How do I make an enemy chase the player in Unity?
Add a NavMeshAgent to the enemy, then call agent.SetDestination(player.transform.position) every frame in Update(), which continuously recalculates the path toward the player's current location.
How do I make an NPC patrol between points?
Store an array of waypoint Transforms, call SetDestination() toward the current waypoint, check agent.remainingDistance combined with !agent.pathPending to detect arrival, then advance to the next waypoint in the array.
What does Stopping Distance do on a NavMeshAgent?
It defines how close the agent needs to get to its destination before it is considered to have arrived, useful for preventing an enemy from walking directly on top of the player before stopping.
Why does my patrol script think the agent arrived immediately?
This usually happens when remainingDistance is checked before the path calculation has finished. Always check !agent.pathPending alongside remainingDistance to avoid this false positive.
Can I use NavMesh with the Animator system?
Yes. Drive the Animator's Speed parameter using agent.velocity.magnitude divided by agent.speed, which produces a normalized value that works well with the same Blend Tree setup used for player characters.
What is a NavMesh Obstacle?
It is a component you add to dynamic objects, like doors or movable crates, so that NavMeshAgents correctly detect and path around them at runtime, since the originally baked NavMesh does not automatically update for moving objects.
Do I need to re-bake the NavMesh if I move level geometry?
Yes. The NavMesh is a static snapshot calculated at bake time. Any meaningful change to walls, floors, or other Navigation Static geometry requires re-baking for the pathfinding data to stay accurate.
Can multiple NavMeshAgents avoid colliding with each other?
Yes, NavMeshAgent includes built-in avoidance behavior that helps agents steer around each other, though very narrow passages with many agents can still cause some congestion depending on Agent Radius and avoidance quality settings.
Is NavMesh suitable for mobile games?
Yes, but the number of simultaneously active pathfinding agents should be managed carefully, since each one adds CPU cost. Refer to our Mobile Optimization guide for general performance management strategies.
Action Steps
- Install the AI Navigation package and bake your first NavMesh on a simple test level with at least one wall obstacle.
- Add a NavMeshAgent to a test character and build the EnemyChase script, targeting your existing Character Controller player.
- Build the EnemyPatrol script with several waypoints and confirm the enemy loops correctly between them.
- Connect the NavMeshAnimatorBridge script to drive your existing Animator Controller's Speed parameter from the same guide.
- Test what happens when you move a wall without re-baking, to see firsthand why re-baking after layout changes matters.
Next Topics To Learn
- Unity Character Controller Explained for Complete Beginners — the player movement system most NavMesh enemies will target.
- Unity Animator and Animation System Explained — connect NavMeshAgent movement to proper walk and run animations.
- Unity Mobile Optimization Guide — manage performance when scaling up the number of active AI agents.
No comments:
Post a Comment