Search Unity

Question Building a NavMesh at run-time using Unity.AI.Navigation and NavMeshSurface

Discussion in 'Navigation' started by trzy, Dec 29, 2022.

  1. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    Hi,

    I'm building an AR experience where I receive plane anchors (just GameObjects with a child quad mesh). I'd like to turn these into navigable surfaces and have been looking at Unity.AI.Navigation. However, I'm seemingly unable to actually create a navmesh on the planes. Here is my code:

    Code (csharp):
    1.  
    2.         foreach (PlayspaceAnchor anchor in _playspaceAnchorTopic.Anchors)
    3.         {
    4.             if (anchor.IsOfClass(classLabel: PlayspaceClass.Label.Floor))
    5.             {
    6.                 NavMeshSurface surface = anchor.gameObject.AddComponent<NavMeshSurface>();
    7.                 surface.AddData();
    8.                 surface.BuildNavMesh();
    9.  
    10.                 _testAgent?.gameObject.SetActive(true);
    11.                 _testAgent?.Warp(newPosition: anchor.transform.position);
    12.             }
    13.         }
    Pretty simple: I add the NavMeshSurface component and call the build function (a bit concerned that this method is not async, btw). Next, to test it out, I have a reference to a NavMeshAgent and I try to warp it to the center of that plane. But when the script that controls that agent tries to select a new destination, I get:

    Code (csharp):
    1.  
    2. "GetRemainingDistance" can only be called on an active agent that has been placed on a NavMesh.
    3. UnityEngine.StackTraceUtility:ExtractStackTrace ()
    4. EnemyBehavior:Update () (at Assets/Scripts/AI/EnemyBehavior.cs:90)
    5.  
    Indicating that a NavMesh probably has not been constructed. Using the Scene view, I don't actually see any NavMesh geometry although the NavMeshSurface component was successfully added as expected.

    I've also tried using the old NavMeshBuilder system but my code (which worked in Unity 5.6) no longer appears to work. No NavMesh components appear to be created and no NavMesh is visible in the Scene editor.

    Any tips or examples? The docs are pretty sparse.

    Thanks,

    Bart
     
  2. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    343
    Not sure how much of a help this will be for you but here is a snippet of my code.
    Note I also use MessageDispatcher but you could use whatever or just remove it.

    You could subscribe to OnBuilt event then add your agents to the navmesh.

    Code (CSharp):
    1. using com.ootii.Messages;
    2. using System.Collections;
    3. using Unity.AI.Navigation;
    4. using UnityEngine;
    5.  
    6. namespace Apoth
    7. {
    8.     public class NavigationBuilder : MonoBehaviour
    9.     {
    10.         public bool debugMode = false;
    11.  
    12.         public bool gridsArePrebaked = false;
    13.  
    14.         public NavMeshSurface surface;
    15.  
    16.         public bool NavMeshBuilt { get; private set; } = false;
    17.  
    18.         public static NavigationBuilder instance;
    19.  
    20.         public static OnInitialized OnBuilt;
    21.  
    22.  
    23.         void Awake()
    24.         {
    25.             if (instance == null)
    26.             {
    27.                 instance = this;
    28.             }
    29.             else
    30.             {
    31.                 Destroy(gameObject);
    32.                 return;
    33.             }
    34.         }
    35.  
    36.         private void OnEnable()
    37.         {
    38.             if (debugMode)
    39.                 Debug.Log("NavigationBuilder - OnEnable");
    40.  
    41.             if (gridsArePrebaked)
    42.                 OnNavMeshBuilt();
    43.             else
    44.                 MessageDispatcher.AddListener("CreateGridMessage", OnCreateGridMessageReceived, true);
    45.         }
    46.  
    47.         private void OnDisable()
    48.         {
    49.             if (debugMode)
    50.                 Debug.Log("NavigationBuilder - OnDisable");
    51.  
    52.             MessageDispatcher.RemoveListener("CreateGridMessage", OnCreateGridMessageReceived);
    53.         }
    54.  
    55.         public void OnCreateGridMessageReceived(IMessage rMessage)
    56.         {
    57.             Debug.Log("NavigationBuilder - OnCreateGridMessageReceived");
    58.  
    59.             CreateGridMessage cgm = (CreateGridMessage)rMessage.Data;
    60.  
    61.             Bounds? bounds = null;
    62.  
    63.             if (cgm != null)
    64.             {
    65.                 bounds = cgm.dungeonBounds;
    66.             }
    67.  
    68.             StartCoroutine(BuildNavMeshAfterDelay(1, bounds));
    69.         }
    70.  
    71.         IEnumerator BuildNavMeshAfterDelay(float delayTime, Bounds? bounds)
    72.         {
    73.             yield return new WaitForSeconds(delayTime);
    74.  
    75.             if (bounds.HasValue)
    76.             {
    77.                 surface.size = bounds.Value.size;
    78.                 surface.center = bounds.Value.center;
    79.             }
    80.  
    81.             surface.BuildNavMesh();
    82.  
    83.             Invoke(nameof(OnNavMeshBuilt), 1);
    84.         }
    85.  
    86.         public virtual void OnNavMeshBuilt()
    87.         {
    88.             Debug.Log("NavigationBuilder - OnNavMeshBuilt");
    89.  
    90.             NavMeshBuilt = true;
    91.  
    92.             OnBuilt?.Invoke();
    93.         }
    94.     }
    95. }
     
    CasualT_Bossfight likes this.
  3. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    Thanks -- I will try this out. The key differences I'm seeing are:

    - Explicit definition of size and center.
    - NavMeshSurface already exists on object (I did try this as well by placing this component on the anchor prefabs I instantiate).

    When the nav mesh is built, is it visible in the Scene window?
     
  4. LootlabGames

    LootlabGames

    Joined:
    Nov 21, 2014
    Posts:
    343
    Yes you can see it if you have gizmos on and Show NavMesh checked.
    upload_2022-12-30_13-49-22.png
     

    Attached Files:

  5. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    Still doesn't work for me but I did some tests and am discovering that apparently it doesn't like quad geometry? I'm playing around in the editor manually baking navmeshes and realizing that quads don't seem to work but planes do. Doesn't matter how large the quad is, it seems to be failing to sample it and I don't see anything online about this being a problem for others.
     
    Last edited: Dec 30, 2022