NavMeshAgent outside of NavMesh Bounds moves to the border of the Bounds when NavMesh is built

Hello

It seems that when you create NavMesh using NavMeshBuilder.UpdateNavMeshData the NavMeshAgents that are supposed to be outside of that NavMesh bounds (but close enough to it) are teleported to the NavMesh bounds border.

This seems like a noticeable bug, but I was not able to find anything regarding it, unfortunately. So maybe it’s not a bug (no idea what might be the logic behind such a feature, but who knows)? And maybe I can turn this off somehow?

How to reproduce:
Create a manager script that updates NavMesh settings that you can manually trigger during gameplay (I do this by pressing Q key). The whole script (you can just copy-paste it):

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class TestNavMeshBug : MonoBehaviour
{
    private void Awake()
    {
        // This things can be created only once
        _settings1 = NavMesh.GetSettingsByID(0);
        _navMeshData1 = new NavMeshData();
        NavMesh.AddNavMeshData(_navMeshData1);
        // -----
    }

    // NavMesh Bounds parameters
    [SerializeField] private Transform _boundsCenter;
    [SerializeField] private float _bounds_Width = 100f;
    [SerializeField] private float _bounds_Height = 100f;
    // -----

    // All other parameters needed for NavMeshBuilder.UpdateNavMeshData
    private List<NavMeshBuildSource> _sources = new List<NavMeshBuildSource>();
    private NavMeshBuildSettings _settings1;
    private NavMeshData _navMeshData1;
    // -----

    private void Update()
    {
        if (Input.GetKeyDown("q"))
        {
            RecreateNavMesh();
        }
    }

    public void AddSource(NavMeshBuildSource source) // Objects will add themselves to Sources
    {
        _sources.Add(source);
    }
    public void RemoveSource(NavMeshBuildSource source) // And objects will also remove themselves when destroyed
    {
        _sources.Remove(source);
    }

    private void RecreateNavMesh()
    {
        Bounds bounds = new Bounds(_boundsCenter.position, new Vector3(_bounds_Width, 1f, _bounds_Height));
        NavMeshBuilder.UpdateNavMeshData(_navMeshData1, _settings1, _sources, bounds);
    }
}

Create some a single NavMesh source that will be a huge walkabe plane. Add it to the Sources lift (the one that in the first manager). I do that on Start. Again, the whole script:

using UnityEngine;
using UnityEngine.AI;

public class NavMeshObj : MonoBehaviour
{
    [SerializeField] private TestNavMeshBug _testNavMeshBug;
    private void Start()
    {
        CreateNavMeshSource();
        _testNavMeshBug.AddSource(_ourNavMeshSource);
    }

    private void OnDisable()
    {
        _testNavMeshBug.RemoveSource(_ourNavMeshSource);
    }

    [SerializeField] private AreaType _areaType = AreaType.NotWalkable; // 0 - walkable, 1 - not walkable
    [SerializeField] private NavMeshBuildSourceShape _shape = NavMeshBuildSourceShape.Mesh;
    [SerializeField] private MeshFilter _ourMeshFilter;
    private Matrix4x4 TransformMatrix { get { return this.transform.localToWorldMatrix; } }

    private NavMeshBuildSource _ourNavMeshSource = new NavMeshBuildSource();
    private void CreateNavMeshSource()
    {
        _ourNavMeshSource.area = (int)_areaType;
        _ourNavMeshSource.shape = _shape;
        _ourNavMeshSource.sourceObject = _ourMeshFilter.mesh;
        _ourNavMeshSource.transform = TransformMatrix;
    }

    private enum AreaType
    {
        Walkable = 0,
        NotWalkable = 1,
    }
}

In the scene you need a Manager (first script), A plane with the second script. Any Transform object that you can move to mark the center of the Bounds (for the first script). And any other object with NavMesh agent with no other scripts on it. NavMesh agent will just stand outside of the bounds:

Press Q to Update the NavMesh:

And this will happen every time. Move the Bounds center (or change it’s size) to exclude the NavMeshAgent object. Press Q again, NavMeshAgent is teleported to the bounds border again.

If that is expected behaviour, does anyone know how to turn that off, maybe? Thank you

Just in case anyone else will land on this page 8 years later. QA confirmed that this behavior is by design. NavMeshAgents teleport ot the nearest NavMesh border (even if they are outside of the bounds). This is needed, for example, to move your NavMesh agents outside of the wall if you spawned it inside the wall for some reason.

So you have to work around that. For example, when you create new Bounds, you can notify all your NavMeshAgents about that and check if they are inside the bounds. If they are, turn NavMeshAgent component on (and update the path, probably). If they are not - turn NavMeshAgent component off. Then recreate the NavMesh using these bounds (using Nav Mesh Builder or whatever).