Applying NavMesh to the spatial mesh obtained through spatial recognition using MRTK3

Nice to meet you. I am currently trying to apply NavMesh to the spatial mesh obtained by spatial recognition using unity2022.3.52 and MRTK3. I would be grateful for your help.
I’m trying to apply NavMesh using the attached script, but the creation of NavMesh fails.

As I cannot attach files for new users,I will put it in text.

SpatialAwarenessNavMesh.cs

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

using UnityEngine.XR.ARFoundation;
using Unity.AI.Navigation;

namespace SpatialAwarenessNavMesh
{

    public class SpatialAwarenessNavMesh : MonoBehaviour
    {
        /// <summary>
        /// Value indicating whether or not this script has registered for spatial awareness events.
        /// このスクリプトが SpatialAwareness イベントに登録されているかどうかを示す値。
        /// </summary>
        private bool isRegistered = false;
        private ARMeshManager arMeshManager;
        private void Start()
        {
            // AR Mesh Managerの取得
            arMeshManager = FindObjectOfType<ARMeshManager>();
            RegisterEventHandlers();
        }

        private void OnEnable()
        {
            RegisterEventHandlers();
        }

        private void OnDisable()
        {
            UnregisterEventHandlers();
        }

        private void OnDestroy()
        {
            UnregisterEventHandlers();
        }

        /// <summary>
        /// Registers for the spatial awareness system events.
        /// </summary>
        private void RegisterEventHandlers()
        {
            if (!isRegistered && arMeshManager != null)
            {
                // メッシュの生成イベントをリッスン
                arMeshManager.meshesChanged += OnMeshesChanged;
                isRegistered = true;
            }
        }

        /// <summary>
        /// Unregisters from the spatial awareness system events.
        /// </summary>
        private void UnregisterEventHandlers()
        {
            if (isRegistered && arMeshManager != null)
            {
                arMeshManager.meshesChanged -= OnMeshesChanged;
                isRegistered = true;
            }
        }

        private void OnMeshesChanged(ARMeshesChangedEventArgs args)
        {
            if (args.added != null)
            {
                foreach (var meshFilter in args.added)
                {
                    // NavMeshSourceTag をオブジェクトに追加
                    meshFilter.gameObject.AddComponent<NavMeshSourceTag>();
                    Debug.Log($"Tracking mesh");
                }
            }

            if (args.updated != null)
            {
                foreach (var meshFilter in args.updated)
                {
                    Debug.Log($"Update mesh");
                    // NavMeshSourceTag をオブジェクトに追加
                   NavMeshSourceTag tag = meshFilter.gameObject.GetComponent<NavMeshSourceTag>();
                    if (tag == null)
                    {
                        meshFilter.gameObject.AddComponent<NavMeshSourceTag>();
                    }
                }
            }
        }
    }
}

LocalNavMeshBuilder.cs

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


// Build and update a localized navmesh from the sources marked by NavMeshSourceTag
[DefaultExecutionOrder(-102)]
public class LocalNavMeshBuilder : MonoBehaviour
{
    // The center of the build
    public Transform m_Tracked;

    // The size of the build bounds
    public Vector3 m_Size = new Vector3(80.0f, 20.0f, 80.0f);

    NavMeshData m_NavMesh;
    AsyncOperation m_Operation;
    NavMeshDataInstance m_Instance;
    List<NavMeshBuildSource> m_Sources = new List<NavMeshBuildSource>();

    IEnumerator Start()
    {
        while (true)
        {
            UpdateNavMesh(true);
            yield return m_Operation;
        }
    }

    void OnEnable()
    {
        // Construct and add navmesh
        m_NavMesh = new NavMeshData();
        m_Instance = NavMesh.AddNavMeshData(m_NavMesh);
        if (m_Tracked == null)
            m_Tracked = transform;
        UpdateNavMesh(false);
    }

    void OnDisable()
    {
        // Unload navmesh and clear handle
        m_Instance.Remove();
    }

    void UpdateNavMesh(bool asyncUpdate = false)
    {
        NavMeshSourceTag.Collect(ref m_Sources);
        var defaultBuildSettings = NavMesh.GetSettingsByID(0);
        var bounds = QuantizedBounds();
        bool isUpdateNavMesh = false;
        if (asyncUpdate)
            m_Operation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
        else
            isUpdateNavMesh = NavMeshBuilder.UpdateNavMeshData(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
        Debug.Log("UpdateNavMesh:"+ isUpdateNavMesh);
        Debug.Log("m_NavMesh:" + m_NavMesh);
        Debug.Log("defaultBuildSettings,:" + defaultBuildSettings);
        Debug.Log("m_Sources:" + m_Sources);
        Debug.Log("bounds:" + bounds);
    }

    static Vector3 Quantize(Vector3 v, Vector3 quant)
    {
        float x = quant.x * Mathf.Floor(v.x / quant.x);
        float y = quant.y * Mathf.Floor(v.y / quant.y);
        float z = quant.z * Mathf.Floor(v.z / quant.z);
        return new Vector3(x, y, z);
    }

    Bounds QuantizedBounds()
    {
        // Quantize the bounds to update only when theres a 10% change in size
        var center = m_Tracked ? m_Tracked.position : transform.position;
        return new Bounds(Quantize(center, 0.1f * m_Size), m_Size);
    }

    void OnDrawGizmosSelected()
    {
        if (m_NavMesh)
        {
            Gizmos.color = Color.green;
            Gizmos.DrawWireCube(m_NavMesh.sourceBounds.center, m_NavMesh.sourceBounds.size);
        }

        Gizmos.color = Color.yellow;
        var bounds = QuantizedBounds();
        Gizmos.DrawWireCube(bounds.center, bounds.size);

        Gizmos.color = Color.green;
        var center = m_Tracked ? m_Tracked.position : transform.position;
        Gizmos.DrawWireCube(center, m_Size);
    }
}

NavMeshSourceTag.cs

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

// Tagging component for use with the LocalNavMeshBuilder
// Supports mesh-filter and terrain - can be extended to physics and/or primitives
[DefaultExecutionOrder(-200)]
public class NavMeshSourceTag : MonoBehaviour
{
    // Global containers for all active mesh/terrain tags
    public static List<MeshFilter> m_Meshes = new List<MeshFilter>();
    public static List<Terrain> m_Terrains = new List<Terrain>();

    void OnEnable()
    {
        var m = GetComponent<MeshFilter>();
        if (m != null)
        {
            m_Meshes.Add(m);
        }

        var t = GetComponent<Terrain>();
        if (t != null)
        {
            m_Terrains.Add(t);
        }
    }

    void OnDisable()
    {
        var m = GetComponent<MeshFilter>();
        if (m != null)
        {
            m_Meshes.Remove(m);
        }

        var t = GetComponent<Terrain>();
        if (t != null)
        {
            m_Terrains.Remove(t);
        }
    }

    // Collect all the navmesh build sources for enabled objects tagged by this component
    public static void Collect(ref List<NavMeshBuildSource> sources)
    {
        sources.Clear();

        for (var i = 0; i < m_Meshes.Count; ++i)
        {
            var mf = m_Meshes[i];
            if (mf == null) continue;

            var m = mf.sharedMesh;
            if (m == null) continue;

            var s = new NavMeshBuildSource();
            s.shape = NavMeshBuildSourceShape.Mesh;
            s.sourceObject = m;
            s.transform = mf.transform.localToWorldMatrix;
            s.area = 0;
            sources.Add(s);
        }

        for (var i = 0; i < m_Terrains.Count; ++i)
        {
            var t = m_Terrains[i];
            if (t == null) continue;

            var s = new NavMeshBuildSource();
            s.shape = NavMeshBuildSourceShape.Terrain;
            s.sourceObject = t.terrainData;
            // Terrain system only supports translation - so we pass translation only to back-end
            s.transform = Matrix4x4.TRS(t.transform.position, Quaternion.identity, Vector3.one);
            s.area = 0;
            sources.Add(s);
        }
    }
}

When you say “fails” do you get a message or error in the log?

1 Like

Thanks for the reply.
NavMeshBuilder.UpdateNavMeshData(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
Because I was receiving false as the return value of this method.
I assumed it was failing.