Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Does the component navigation work with terrain trees yet?

Discussion in 'Navigation' started by Tyrathect, Aug 14, 2017.

  1. Tyrathect

    Tyrathect

    Joined:
    Jul 10, 2012
    Posts:
    38
    It seemed pretty decent, but it has (had?) two serious flaws:
    1. It won't work if you have multiple scene files loaded. It throws errors.
    2. It doesn't work with trees on the terrain. It just ignores them.
     
  2. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    161
    I can't comment on the multiple scene issue, but have you tried giving your tree prefabs NavMeshModifierVolumes?
     
  3. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    It does not work with trees out of the box like the built in navmesh system. Please comment on the issue on github so we can finally have this fixed https://github.com/Unity-Technologies/NavMeshComponents/issues/30

    If you know any other solution please let me know, I haven't tried giving the trees NavMeshModifierVolumes and I cannot test it right now, if someone can do that would be awesome.
     
  4. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    Have you tried giving your tree prefabs NavMeshModifierVolumes ? It is not working for me :(
     
  5. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    161
    How do you bake/update your navmeshes? With NavMeshSurface or LocalNavMeshBuilder?
     
  6. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    I have a navmesh surface component in the scene and I click the Bake button from the navmesh surface script component.

    If I use Navigation > Bake, I am not really happy with the results, I see some parts of the terrain not baked properly, where the navmesh surface bake does it just right.
     
  7. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    161
    Well, that just doesn't work. The "obsolete" bake in the Unity UI does not work with NavMeshModifiers and NavMeshModifierVolumes. You need to use the bake function of the NavMeshSurface from the new Navgiation components.

    Can you post a screenshot, of the terrain so we can see why it does not bake properly?
     
  8. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    It has gaps that are not present when I bake from the NM Surface component, so I want to stick with that. The problem is that it does not detect unity's terrain trees :(
     
  9. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    161
    AFAIK, there is no solution for this if you stick using the old navmesh bake function.
     
  10. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    Well I am not using the old bake function and by old I am refering to the built in thats in the Navigation window. I am using the one from the navmesh surface game object.
     
  11. Naalei

    Naalei

    Joined:
    Jan 15, 2018
    Posts:
    1
    Hi,
    I ran into the same issue with terrain tree and NavMeshSurface and wasn't able to find a solution on google !
    So I tried to patch NavMeshSurface script myself and I'm quite happy with the result !

    The code is still missing a lot of things like using the real size of the tree (you can use treePrototypes to retrieve the tree prefab), colliders and details meshes, but it is suited to my needs !
    It is just an example on how to implement tree baking in NavMeshSurface.

    Replace NavMeshSurface.CollectSource() with this method.
    (Added code is between /***** Terrain trees *****/ and /***** End ofTerrain trees *****/)

    There is still an issue if your terrain is not set to position 0, 0, 0
    The fakeGameObject.transform.position should take into account terrain transform (position, rotation and scale)


    Hope it can help some people !
    (and sorry for my bad english !)

    Code (CSharp):
    1.  
    2.         List<NavMeshBuildSource> CollectSources()
    3.         {
    4.             var sources = new List<NavMeshBuildSource>();
    5.             var markups = new List<NavMeshBuildMarkup>();
    6.  
    7.             List<NavMeshModifier> modifiers;
    8.             if (m_CollectObjects == CollectObjects.Children)
    9.             {
    10.                 modifiers = new List<NavMeshModifier>(GetComponentsInChildren<NavMeshModifier>());
    11.                 modifiers.RemoveAll(x => !x.isActiveAndEnabled);
    12.             }
    13.             else
    14.             {
    15.                 modifiers = NavMeshModifier.activeModifiers;
    16.             }
    17.  
    18.             foreach (var m in modifiers)
    19.             {
    20.                 if ((m_LayerMask & (1 << m.gameObject.layer)) == 0)
    21.                     continue;
    22.                 if (!m.AffectsAgentType(m_AgentTypeID))
    23.                     continue;
    24.                 var markup = new NavMeshBuildMarkup();
    25.                 markup.root = m.transform;
    26.                 markup.overrideArea = m.overrideArea;
    27.                 markup.area = m.area;
    28.                 markup.ignoreFromBuild = m.ignoreFromBuild;
    29.                 markups.Add(markup);
    30.             }
    31.          
    32.             if (m_CollectObjects == CollectObjects.All)
    33.             {
    34.                 NavMeshBuilder.CollectSources(null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    35.             }
    36.             else if (m_CollectObjects == CollectObjects.Children)
    37.             {
    38.                 NavMeshBuilder.CollectSources(transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    39.             }
    40.             else if (m_CollectObjects == CollectObjects.Volume)
    41.             {
    42.                 Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
    43.                 var worldBounds = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size));
    44.                 NavMeshBuilder.CollectSources(worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    45.             }
    46.  
    47.             /***** Terrain trees *****/
    48.  
    49.             var fakeGameObject = new GameObject();
    50.             // Required to have a Transform instance to call localToWorldMatrix (I'm fairly bad at mathematics so maybe there is an other solution !)
    51.  
    52.             var size = Terrain.activeTerrain.terrainData.size;
    53.             // Do not use Terrain.activeTerrain but maybe add a properties or detect terrains inside the bounding box of NavMeshSurface
    54.             // Then simply loop through all selected terrains
    55.             foreach (var tree in Terrain.activeTerrain.terrainData.treeInstances)
    56.             {
    57.                 var prototype = Terrain.activeTerrain.terrainData.treePrototypes[tree.prototypeIndex];
    58.                 // Use prototype.prefab to reach the prefab of the tree
    59.                 // not used in this example
    60.  
    61.                 fakeGameObject.transform.position = new Vector3(tree.position.x * size.x, tree.position.y * size.y, tree.position.z * size.z) ;
    62.                 fakeGameObject.transform.rotation = Quaternion.AngleAxis(tree.rotation, Vector3.up);
    63.                 fakeGameObject.transform.localScale = new Vector3(1, 1, 1);
    64.  
    65.                 var src = new NavMeshBuildSource();
    66.                 src.transform = fakeGameObject.transform.localToWorldMatrix;
    67.                 src.shape = NavMeshBuildSourceShape.Box; // update this to your convenience
    68.                 src.size = new Vector3(1f, 1f, 1f); // update this according to tree heightScale / widthScale and the prefab size.
    69.                 sources.Add(src);
    70.             }
    71.             DestroyImmediate(fakeGameObject);
    72.  
    73.             /***** End ofTerrain trees *****/
    74.  
    75.             if (m_IgnoreNavMeshAgent)
    76.                 sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshAgent>() != null));
    77.  
    78.             if (m_IgnoreNavMeshObstacle)
    79.                 sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshObstacle>() != null));
    80.  
    81.             AppendModifierVolumes(ref sources);
    82.  
    83.             return sources;
    84.         }
     
    Last edited: Jan 15, 2018
    BrandStone, skinwalker and JBR-games like this.
  12. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    Thanks for the workaround, I haven't tested it, because I found another solution - exporting the tree colliders in the scene and rebaking the navmesh. Hopefully your solution will help to someone!
     
  13. WhiteWolfProject

    WhiteWolfProject

    Joined:
    Jan 29, 2017
    Posts:
    4
    Thanks ! Its work fine.

    I add terran position:

    public Terrain mTerrain;
    ....
    Vector3 pos = mTerrain.transform.position;
    ...
    fakeGameObject.transform.position = new Vector3(tree.position.x * size.x + pos.x,
    tree.position.y * size.y + pos.y,
    tree.position.z * size.z + pos.z);
     
    BrandStone likes this.
  14. Buka

    Buka

    Joined:
    Feb 22, 2013
    Posts:
    37
    This is still not working, tried to use NavMesh components but they ignore terrain trees for some reason if I bake with NavMeshSurface. Can somebody provide a solution? Tried above and still the same, if I place trees manually it works but from terrain trees, it does not work at all. Please help somebody
     
  15. skinwalker

    skinwalker

    Joined:
    Apr 10, 2015
    Posts:
    315
    I dont have other solution than buying A* project and using it, thats what I ended up doing.
     
  16. Buka

    Buka

    Joined:
    Feb 22, 2013
    Posts:
    37
    We are making MMO (for a while now) and these navigation problems are so annoying. I Was hoping that they will just fix that baking problem with trees and we could just use that. You can see on this example image (some terrain where I tried to bake things properly) I do get weird path around trees if default Unity Navigation Bake is used, looks really weird in the game when players are running around. NavMeshSurface has option to bake colliders only so when I try to use that i do get better results but only if trees are placed by hand, not terrain trees sadly... Would be great to not go and use A* at this point since we based on NavMeshAgent our combat, network, navigation...But if we have to switch as @skinwalker suggested then we will probably.
     

    Attached Files:

    ModLunar likes this.
  17. HedwigDoets

    HedwigDoets

    Joined:
    Dec 7, 2016
    Posts:
    2

    Hi! I fixed the thing where if the terrain is not on zero it doesn't work.
    Here's the whole thing independent of terrain position:
    Code (CSharp):
    1.  List<NavMeshBuildSource> CollectSources()
    2.         {
    3.             var sources = new List<NavMeshBuildSource>();
    4.             var markups = new List<NavMeshBuildMarkup>();
    5.  
    6.             List<NavMeshModifier> modifiers;
    7.             if (m_CollectObjects == CollectObjects.Children)
    8.             {
    9.                 modifiers = new List<NavMeshModifier>(GetComponentsInChildren<NavMeshModifier>());
    10.                 modifiers.RemoveAll(x => !x.isActiveAndEnabled);
    11.             }
    12.             else
    13.             {
    14.                 modifiers = NavMeshModifier.activeModifiers;
    15.             }
    16.  
    17.             foreach (var m in modifiers)
    18.             {
    19.                 if ((m_LayerMask & (1 << m.gameObject.layer)) == 0)
    20.                     continue;
    21.                 if (!m.AffectsAgentType(m_AgentTypeID))
    22.                     continue;
    23.                 var markup = new NavMeshBuildMarkup();
    24.                 markup.root = m.transform;
    25.                 markup.overrideArea = m.overrideArea;
    26.                 markup.area = m.area;
    27.                 markup.ignoreFromBuild = m.ignoreFromBuild;
    28.                 markups.Add(markup);
    29.             }
    30.  
    31.             if (m_CollectObjects == CollectObjects.All)
    32.             {
    33.                 NavMeshBuilder.CollectSources(null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    34.             }
    35.             else if (m_CollectObjects == CollectObjects.Children)
    36.             {
    37.                 NavMeshBuilder.CollectSources(transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    38.             }
    39.             else if (m_CollectObjects == CollectObjects.Volume)
    40.             {
    41.                 Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
    42.                 var worldBounds = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size));
    43.                 NavMeshBuilder.CollectSources(worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    44.             }
    45.  
    46.             /***** Terrain trees *****/
    47.  
    48.             var fakeGameObject = new GameObject();
    49.             // Required to have a Transform instance to call localToWorldMatrix (I'm fairly bad at mathematics so maybe there is an other solution !)
    50.  
    51.             var size = Terrain.activeTerrain.terrainData.size;
    52.             // Do not use Terrain.activeTerrain but maybe add a properties or detect terrains inside the bounding box of NavMeshSurface
    53.             // Then simply loop through all selected terrains
    54.             foreach (var tree in Terrain.activeTerrain.terrainData.treeInstances)
    55.             {
    56.                 var prototype = Terrain.activeTerrain.terrainData.treePrototypes[tree.prototypeIndex];
    57.                 // Use prototype.prefab to reach the prefab of the tree
    58.                 // not used in this example
    59.  
    60.                 fakeGameObject.transform.position = new Vector3(tree.position.x * size.x, tree.position.y * size.y, tree.position.z * size.z);
    61.                 fakeGameObject.transform.position += Terrain.activeTerrain.GetPosition();
    62.                 fakeGameObject.transform.rotation = Quaternion.AngleAxis(tree.rotation, Vector3.up);
    63.                 fakeGameObject.transform.localScale = new Vector3(1, 1, 1);
    64.  
    65.                 var src = new NavMeshBuildSource();
    66.                 src.transform = fakeGameObject.transform.localToWorldMatrix;
    67.                 src.shape = NavMeshBuildSourceShape.Box; // update this to your convenience
    68.                 src.size = new Vector3(1f, 1f, 1f); // update this according to tree heightScale / widthScale and the prefab size.
    69.                 sources.Add(src);
    70.             }
    71.             DestroyImmediate(fakeGameObject);
    72.  
    73.             /***** End ofTerrain trees *****/
    74.  
    75.             if (m_IgnoreNavMeshAgent)
    76.                 sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshAgent>() != null));
    77.  
    78.             if (m_IgnoreNavMeshObstacle)
    79.                 sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshObstacle>() != null));
    80.  
    81.             AppendModifierVolumes(ref sources);
    82.  
    83.             return sources;
    84.         }
     
    ModLunar likes this.
  18. Acreates

    Acreates

    Joined:
    Dec 12, 2016
    Posts:
    25
    For us non engineers. I can't find "NavMeshSurface.CollectSource()" has something changed? Can someone provide the entire script here?

    (Really annoying that the nav mesh doesn't bake Trees)
     
  19. HeavyArt

    HeavyArt

    Joined:
    Mar 5, 2015
    Posts:
    1
    Works great if change fakeGameObject.transform.localScale from Vector3(1, 1, 1) to Vector3(2, 10, 2);

    Code (CSharp):
    1.      
    2.         List<NavMeshBuildSource> CollectSources()
    3.         {
    4.             var sources = new List<NavMeshBuildSource>();
    5.             var markups = new List<NavMeshBuildMarkup>();
    6.  
    7.             List<NavMeshModifier> modifiers;
    8.             if (m_CollectObjects == CollectObjects.Children)
    9.             {
    10.                 modifiers = new List<NavMeshModifier>(GetComponentsInChildren<NavMeshModifier>());
    11.                 modifiers.RemoveAll(x => !x.isActiveAndEnabled);
    12.             }
    13.             else
    14.             {
    15.                 modifiers = NavMeshModifier.activeModifiers;
    16.             }
    17.  
    18.             foreach (var m in modifiers)
    19.             {
    20.                 if ((m_LayerMask & (1 << m.gameObject.layer)) == 0)
    21.                     continue;
    22.                 if (!m.AffectsAgentType(m_AgentTypeID))
    23.                     continue;
    24.                 var markup = new NavMeshBuildMarkup();
    25.                 markup.root = m.transform;
    26.                 markup.overrideArea = m.overrideArea;
    27.                 markup.area = m.area;
    28.                 markup.ignoreFromBuild = m.ignoreFromBuild;
    29.                 markups.Add(markup);
    30.             }
    31.  
    32.             if (m_CollectObjects == CollectObjects.All)
    33.             {
    34.                 NavMeshBuilder.CollectSources(null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    35.             }
    36.             else if (m_CollectObjects == CollectObjects.Children)
    37.             {
    38.                 NavMeshBuilder.CollectSources(transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    39.             }
    40.             else if (m_CollectObjects == CollectObjects.Volume)
    41.             {
    42.                 Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
    43.                 var worldBounds = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size));
    44.                 NavMeshBuilder.CollectSources(worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
    45.             }
    46.  
    47.             /***** Terrain trees *****/
    48.  
    49.             var fakeGameObject = new GameObject();
    50.             // Required to have a Transform instance to call localToWorldMatrix (I'm fairly bad at mathematics so maybe there is an other solution !)
    51.  
    52.             var size = Terrain.activeTerrain.terrainData.size;
    53.             // Do not use Terrain.activeTerrain but maybe add a properties or detect terrains inside the bounding box of NavMeshSurface
    54.             // Then simply loop through all selected terrains
    55.             foreach (var tree in Terrain.activeTerrain.terrainData.treeInstances)
    56.             {
    57.                 var prototype = Terrain.activeTerrain.terrainData.treePrototypes[tree.prototypeIndex];
    58.                 // Use prototype.prefab to reach the prefab of the tree
    59.                 // not used in this example
    60.  
    61.                 fakeGameObject.transform.position = new Vector3(tree.position.x * size.x, tree.position.y * size.y, tree.position.z * size.z);
    62.                 fakeGameObject.transform.position += Terrain.activeTerrain.GetPosition();
    63.                 fakeGameObject.transform.rotation = Quaternion.AngleAxis(tree.rotation, Vector3.up);
    64.                 fakeGameObject.transform.localScale = new Vector3(2, 10, 2);
    65.  
    66.                 var src = new NavMeshBuildSource();
    67.                 src.transform = fakeGameObject.transform.localToWorldMatrix;
    68.                 src.shape = NavMeshBuildSourceShape.Box; // update this to your convenience
    69.                 src.size = new Vector3(1f, 1f, 1f); // update this according to tree heightScale / widthScale and the prefab size.
    70.                 sources.Add(src);
    71.             }
    72.             DestroyImmediate(fakeGameObject);
    73.  
    74.             /***** End ofTerrain trees *****/
    75.  
    76.             if (m_IgnoreNavMeshAgent)
    77.                 sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshAgent>() != null));
    78.  
    79.             if (m_IgnoreNavMeshObstacle)
    80.                 sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshObstacle>() != null));
    81.  
    82.             AppendModifierVolumes(ref sources);
    83.  
    84.             return sources;
    85.         }
    86.  
     
    Last edited: Oct 23, 2018
    cmart likes this.
  20. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    103
    Thank you so much, that was a lot to get me started on the solution I needed. I made some adjustments, including optimizations with getting arrays from the Unity API multiple times, and avoiding the need to create GameObjects. I used Matrix4x4.TRS(...) instead to calculate the localToWorld matrix, even though I don't know how to calculate that mathematically, myself yet ;) haha.


    My version (below) adds support for trees with NavMeshObstacles on their prefab's root GameObject. Specifically, if it DOES find a NavMeshObstacle on the prefab's root GameObject, it will add that as a source to the list, and use the center and sizing of the obstacle.

    I left my commented-out Debug.Log(...) calls in case you wanted to easily uncomment them and see what's going on.

    I can only hope that Unity includes something this vital for the NavMeshComponents. If I get time, I may request it to them, and say "hey, it works already! Here, .. please!!!" haha. Goodluck, and hope this helps :)

    Code (CSharp):
    1. // --- --- --- Terrain trees --- --- ---
    2.  
    3. Terrain terrain = Terrain.activeTerrain;
    4. TerrainData terrainData = terrain.terrainData;
    5. Vector3 size = Terrain.activeTerrain.terrainData.size;
    6. Vector3 terrainPos = terrain.GetPosition();
    7. //Debug.Log("terrainPos = " + terrainPos);
    8. int treesArea = NavMesh.GetAreaFromName("Not Walkable");
    9. if (treesArea < 0) {
    10.     Debug.LogError("Unrecognized area name! The default area will be used instead.");
    11.     treesArea = 0;
    12. }
    13.  
    14. TreePrototype[] treePrototypes = terrainData.treePrototypes;
    15. TreeInstance[] treeInstances = terrainData.treeInstances;
    16. for (int i = 0; i < treeInstances.Length; i++) {
    17.     //treeInstances[i] is the current ACTUAL tree we're going over.
    18.     //the tree prototype is the "template" used by this tree.
    19.     TreePrototype prototype = treePrototypes[treeInstances[i].prototypeIndex];
    20.     GameObject prefab = prototype.prefab;
    21.     NavMeshObstacle obstacle = prefab.GetComponent<NavMeshObstacle>();
    22.     if (obstacle == null)
    23.         continue;
    24.  
    25.     //Debug.Log("treeInstances[" + i + "] info:\n" + treeInstances[i].position + " " + treeInstances[i].rotation + " " + treeInstances[i].widthScale + " " + treeInstances[i].heightScale);
    26.     Vector3 worldTreePos = terrainPos + Vector3.Scale(treeInstances[i].position, size)
    27.         + obstacle.center;
    28.     Quaternion worldTreeRot = Quaternion.Euler(0, treeInstances[i].rotation * Mathf.Rad2Deg, 0);
    29.     Vector3 worldTreeScale = new Vector3(treeInstances[i].widthScale, treeInstances[i].heightScale, treeInstances[i].widthScale);
    30.     //Debug.Log("CREATED MATRIX FOR TRS:\nworldTreePos = " + worldTreePos + "\nworldTreeRot = " + worldTreeRot + "\nworldTreeScale = " + worldTreeScale);
    31.    
    32.     NavMeshBuildSource src = new NavMeshBuildSource();
    33.     src.transform = Matrix4x4.TRS(worldTreePos, worldTreeRot, worldTreeScale);
    34.  
    35.     switch (obstacle.shape) {
    36.         case NavMeshObstacleShape.Capsule:
    37.             src.shape = NavMeshBuildSourceShape.Capsule;
    38.  
    39.             //Unity 2019.2.0f1: BUG!! navMeshObstacle.height returns exactly HALF of the actual height of the obstacle.
    40.             //Use the size property instead.
    41.             src.size = obstacle.size;
    42.             break;
    43.         case NavMeshObstacleShape.Box:
    44.             src.shape = NavMeshBuildSourceShape.Box;
    45.             src.size = obstacle.size;
    46.             break;
    47.         default:
    48.             Debug.LogError("Unsupported type of " + typeof(NavMeshObstacleShape).Name
    49.                 + " for the building of the " + typeof(NavMeshSurface).Name + "! (" + obstacle.shape + ")");
    50.             break;
    51.     }
    52.     src.size = Vector3.Scale(src.size, prefab.transform.localScale);
    53.     //Debug.Log("src.size = " + src.size);
    54.     src.area = treesArea;
    55.     sources.Add(src);
    56. }
    57.  
    58. // --- --- --- End of Terrain trees --- --- ---


    [EDIT]: This code should go in the NavMeshSurface.CollectSources() method. Exactly where may depend on the version of the NavMeshComponents repo that you cloned, I used the 2019.1 branch. I put it right before the lines that use these "ignore" options:

    Code (CSharp):
    1. if (m_IgnoreNavMeshAgent)
    2.     sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshAgent>() != null));
    3.  
    4. if (m_IgnoreNavMeshObstacle)
    5.     sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshObstacle>() != null));
    This should be near the end of the method where it returns the sources.
     
    Last edited: Sep 4, 2019
    RadonRaph likes this.