> For the complete documentation index, see [llms.txt](https://multiset.gitbook.io/multiset/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://multiset.gitbook.io/multiset/unity-sdk/ar-foundation/features/navmesh-navigation.md).

# NavMesh Navigation

Unity's NavMesh system and MultiSet localization work together with no runtime coordinate maths. Bake the NavMesh once in the Editor with your map mesh parented under **MapSpace**, and it will follow the map into the real world every time the device localizes.

{% hint style="info" %}
You do **not** need to re-bake the NavMesh at runtime, and you do **not** need to convert positions with `InverseTransformPoint`. Step 5 below explains why.
{% endhint %}

### 1. Import 3D Mesh from Developer Portal

Download the 3D Mesh (.glb) of a Map or MapSet from the Developer Portal and import it into Unity (under MapSpace Gameobject)

<figure><img src="/files/yOx8sTxgaHtmlJb5IkCI" alt=""><figcaption></figcaption></figure>

### 2. Add Unity NavMesh Surface component to this Mesh

Install Unity NavMesh package: **com.unity.ai.navigation**\
Select the Mesh -> **Component** -> Navigation -> NavMesh Surface

<figure><img src="/files/xatPtgUgnPYLRK48u1zv" alt=""><figcaption></figcaption></figure>

### 3. Bake the NavMesh Surface

Once NavMesh Surface component is added, adjust the NavMesh settings as per your scan under Window -> AI -> Navigation, and then select the Mesh and click on bake.

<div><figure><img src="/files/ZFmSIXY0a0SEDjwZYtQT" alt=""><figcaption></figcaption></figure> <figure><img src="/files/rLXqBVH8yKYphMIArlDx" alt=""><figcaption></figcaption></figure></div>

### 4. Check the baked surface

* Check the baked surface; the blue colour is the detected path that is used later in finding paths. You can adjust the NavMesh surface setting based on your map scan area.<br>
* In some areas of the Mesh ground might not be accurate, in those cases, place planes inside the map just slightly above the ground those planes are just used for NavMesh baking and need to be deactivated later

<figure><img src="/files/FdjJ3AOUEUaAYwiRTu1C" alt=""><figcaption></figcaption></figure>

### 5. How the NavMesh follows real-world localization

This step is not something you implement. It describes what the SDK and Unity already do for you, so that you do not write code you do not need.

**What happens on localization**

When localization succeeds, the MultiSet SDK sets the position and rotation of the **MapSpace** GameObject so that it aligns with the physical space. Everything parented under MapSpace moves with it, including your map mesh and the NavMesh Surface component on it.

**Why the baked NavMesh moves with it**

Unity's `NavMeshSurface` component (from **com.unity.ai.navigation**) registers itself with the navigation system and watches its own transform. When that transform's position or rotation changes, the component removes its baked NavMesh instance and re-adds it at the new pose. Because your NavMesh Surface is a child of MapSpace, this happens automatically the moment MapSpace is moved by localization. The baked data itself is never rebuilt, it is only re-placed, so the cost is negligible.

The practical consequences:

* The walkable surface lines up with the real world as soon as you localize.
* Your `NavMeshAgent` (on the AR camera) and your destinations (parented under MapSpace) are already expressed in the same Unity world space, so `agent.destination = poi.transform.position` is all you need.
* Do **not** call `NavMeshSurface.BuildNavMesh()` at runtime. Re-baking on device is slow and unnecessary.
* Do **not** convert positions with `Transform.InverseTransformPoint` or `Transform.TransformPoint` for navigation. That conversion is only required when a coordinate has to leave the Unity scene graph, for example when it is sent over a network or saved to a backend. See [Multiplayer AR](/multiset/unity-sdk/ar-foundation/features/multiplayer-ar.md) for that case.

{% hint style="warning" %}
Three requirements for this to work:

1. **The NavMesh Surface must be a child of MapSpace.** A surface that lives outside MapSpace stays wherever it was baked and will not follow the map.
2. **Use the NavMesh Surface component, not the legacy scene bake.** NavMesh data baked through the old Navigation Static workflow is fixed in world space and will not follow MapSpace. This is the most common cause of a path that renders in the wrong place after localization.
3. **Keep MapSpace at a uniform scale of 1.** The NavMesh instance is re-placed using position and rotation only, so scale is not applied to it. The SDK never changes the scale of MapSpace, so leave it alone.
   {% endhint %}

**Recalculating a path after localization**

The NavMesh instance is re-placed during Unity's navigation pre-update, so it is correctly positioned from the frame after MapSpace moves. If you calculate a path in the same frame that localization succeeds, that query can still run against the previous placement. Recalculate from the `LocalizationSuccess` event, one frame later:

```csharp
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
using MultiSet;

/// <summary>
/// Recalculates the active path once the map has been aligned to the real world.
/// The NavMesh itself needs no rebuild, only the path query needs to be re-run.
/// </summary>
public class NavigationRefresher : MonoBehaviour
{
    [Tooltip("The MapLocalizationManager in your scene.")]
    public MapLocalizationManager localizationManager;

    [Tooltip("NavMeshAgent attached to the AR camera.")]
    public NavMeshAgent agent;

    [Tooltip("Current navigation destination, parented under MapSpace.")]
    public Transform destination;

    void OnEnable()
    {
        localizationManager.LocalizationSuccess.AddListener(OnLocalized);
    }

    void OnDisable()
    {
        localizationManager.LocalizationSuccess.RemoveListener(OnLocalized);
    }

    void OnLocalized()
    {
        // MapSpace has just moved. The NavMesh Surface under it is re-placed
        // automatically, so all we do is re-run the path query next frame.
        StartCoroutine(RecalculateNextFrame());
    }

    IEnumerator RecalculateNextFrame()
    {
        yield return null;

        if (agent.isOnNavMesh && destination != null)
        {
            agent.SetDestination(destination.position);
        }
    }
}
```

You can also wire this up without code by dragging your script's method onto the `LocalizationSuccess` UnityEvent in the Inspector. See the [MapLocalizationManager](/multiset/unity-sdk/ar-foundation/api-reference/maplocalizationmanager.md) API reference for the full list of events.

{% hint style="info" %}
If background localization is enabled, MapSpace is re-aligned on every successful localization, not just the first one. The NavMesh follows each time. Any world position you cached yourself will go stale, so read positions from the transforms under MapSpace instead of caching `Vector3` values.
{% endhint %}

### 6. Add a Navigation sample in NavMesh

### Attaching the Agent

To set up agent navigation in your AR or camera-based scene, you'll need to follow these key steps:

#### Camera Attachment

Attach the navigation agent to the Main Camera or the primary camera used for the AR session. This ensures the agent's navigation is synchronized with the user's device perspective.

<figure><img src="/files/Fw79L4UZ80HPDq9wEXOt" alt=""><figcaption></figcaption></figure>

#### Path Rendering

By default, agents will continuously move towards their destination. To visualize the path without actual movement, you'll need to:

1. Stop the agent's movement using the `isStopped` property
2. Use the LineRenderer component to draw the calculated navigation path

#### LineRenderer Configuration

Configure the LineRenderer to:

* Render the path's trajectory
* Customize visual properties like width and color
* Provide a clear visual representation of the potential agent movement

Unity automatically calculates the shortest path between two points. Add obstacles and modifiers to improve the pathing.

Check Unity documentation [here](https://docs.unity3d.com/Packages/com.unity.ai.navigation@1.1/manual/CreateNavMeshAgent.html) for detailed explanations of navigation.\
\
Also, check out videos of [Joshua Drewlow](https://www.youtube.com/@joshuadrewlow/videos)'s detailed explanations on Unity + NavMesh for navigation


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://multiset.gitbook.io/multiset/unity-sdk/ar-foundation/features/navmesh-navigation.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
