Search Unity

[SOLVED]Test If the (NavMesh)Agent Has Arrived At The Targeted Location

Discussion in 'Navigation' started by pehlivan2000, May 23, 2015.

  1. pehlivan2000

    pehlivan2000

    Joined:
    May 23, 2015
    Posts:
    20
    Hi,

    ... is it possible to test if the agent has arrived at the location(target)?I didn't find anything about it...
    Here' s a short picture, to explain my problem a bit more:

     
    6real likes this.
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I suggest looking at the docs a little harder. Its all there.
     
    alex_e_m and hippocoder like this.
  3. pehlivan2000

    pehlivan2000

    Joined:
    May 23, 2015
    Posts:
    20
    Yes, I know.It's 'pathStatus', right?But there's no example how to use it.There isn't also a video about it.
     
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
  5. pehlivan2000

    pehlivan2000

    Joined:
    May 23, 2015
    Posts:
    20
    Here are some problems that appear(due Unity 4 and Unity 5?):

    error CS0120: An object reference is required to access non-static member `UnityEngine.NavMeshAgent.pathPending'
    error CS0120: An object reference is required to access non-static member `UnityEngine.NavMeshAgent.remainingDistance'
    error CS0120: An object reference is required to access non-static member `UnityEngine.NavMeshAgent.hasPath'

    And please, don't use this 'LetMeGoogleThatForYou'-S*** anymore. Thanks!
     
    SorraTheOrc, LucSchols and xrm0 like this.
  6. pehlivan2000

    pehlivan2000

    Joined:
    May 23, 2015
    Posts:
    20
    I've already got it!
     
  7. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    What was the solution for this? I am building a Behavior Tree and using a MoveTo Task for debugging.

    1. I set destination.
    2. If pathPending then return RUNNING
    3. If !pathPending && hasPath then return RUNNING

    I still need the following return states...
    4. If invalid destination (off mesh or unreachable) return FAILED
    5. If Agent tried and failed to reach destination return FAILED
    6. If Agent successfully reaches destination return SUCCESS

    I don't see anything in the documentation to test for case 4,5, and 6
     
  8. MysterySoftware

    MysterySoftware

    Joined:
    Sep 18, 2014
    Posts:
    46
    4. To check whether or not the target is unreachable...
    Code (CSharp):
    1. // navpath: The NavMeshPath
    2.  
    3. if (navpath.status == NavMeshPathStatus.PathInvalid || navpath.status == NavMeshPathStatus.PathPartial) {
    4.    // Target is unreachable
    5. }
    5. This is pretty much covered by No. 4

    6. To check if the agent has reached the target...
    Code (CSharp):
    1. // agent: Agent's transform component
    2. // nav: Agent's NavMeshAgent component
    3. // target: Target's transform component
    4.  
    5. if (Vector3.Distance (agent.position, target.position) <= nav.stoppingDistance) {
    6.     // Target reached
    7. }
     
    RiverExplorer likes this.
  9. pehlivan2000

    pehlivan2000

    Joined:
    May 23, 2015
    Posts:
    20
    Thats the solution:

    Code (csharp):
    1.  if(!youragent.pathPending) {
    2.  if(youragent.remainingDistance <= youragent.stoppingDistance) {
    3.    if(!youragent.hasPath | | youragent.velocity.sqrMagnitude == 0f) {
    4.       //...
    5.    }
    6.  }
    7. }
     
    Jasper_Chen likes this.
  10. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    5. Track remainingDistance value, if it doesn't change, your navigator is stuck for some reason... most likely because 5.
    6. Same as 5, but the value is within a target distance threshold (decided on by you)

    When I was dealing with moving my things around, I would have a tolerance for arriving at a point.. if I got within a certain small distance, I would consider that successful arrival, and the agent would then move on to next action.
     
  11. CarterG81

    CarterG81

    Joined:
    Jul 25, 2013
    Posts:
    1,773
    Because google results...

    For anyone finding this in 2017, NavMashAgent.path.status includes 4, 5, & 6. I noticed 6 was not included in this thread.

    1. NavMeshAgent.SetDestination(Vector3)
    2. NavMeshAgent.pathPending
    3. NavMeshAgent.hasPath
    4. NavMeshAgent.path.status == NavMeshPathStatus.PathInvalid //If invalid destination (off mesh or unreachable) return FAILED
    5. NavMeshAgent.path.status == NavMeshPathStatus.PathPartial //If Agent tried and failed to reach destination return FAILED
    6. NavMeshAgent.path.status == NavMeshPathStatus.PathComplete //If Agent successfully reaches destination return SUCCESS
     
    1 person likes this.
  12. SoldierofYHVH

    SoldierofYHVH

    Joined:
    May 31, 2017
    Posts:
    8
    Wow!!! you can't escape nerdy intellectualism even at Unity. Doesn't suprise me!
     
  13. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Well I'm not unity staff, just a glorified spam cleaner and apparently annoying person. Do you have a navmesh related issue?
     
    twobob and CarterG81 like this.
  14. OlliIllustrator

    OlliIllustrator

    Joined:
    Nov 1, 2013
    Posts:
    71
    This is a very helpful thread. Thank you!
     
    pango and SorraTheOrc like this.
  15. maxime66410

    maxime66410

    Joined:
    Mar 16, 2018
    Posts:
    19
    Why this does't work with me ?
     
  16. maxime66410

    maxime66410

    Joined:
    Mar 16, 2018
    Posts:
    19
    And this doe'st work too for my...
     
    alex_e_m likes this.
  17. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    542
    I know this is a huge necro but it's still one of the first google search results, so I wanted to comment on this.
    This code example worked in almost all cases, but there is one specific case that did not work for me.

    When the agent can't find a valid path (for example if you set a value that is outside of the nav mesh or if it is blocked) then in some cases pathPending will still be true while hasPath is also true with the pathStatus being != PathComplete, so basically the agent detected an invalid path and will try (forever?) to find an other valid path.

    To avoid this I added a else condition
    if agent.pathPending && agent.hasPath && agent.pathStatus != NavMeshPathStatus.PathComplete
    in this case I assume that the agent will not find any other valid path and cancel my agent.

    This is a very specific / rare case, so most user will not notice it, but maybe this helps someone.
     
    Last edited: Jul 23, 2021
    hippocoder likes this.
  18. juelzsantana123

    juelzsantana123

    Joined:
    Feb 28, 2019
    Posts:
    17
    I dont understand why Unity team didnt think to raise an event when path ended execution with some status as parameter. This is so simple.
     
    A_Marraff, DwinTeimlon and CarterG81 like this.
  19. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I don't think it's simple. But you can query it all kinds of way for your game. The reason it's not simple is because arrived means very different things in a zombie game than it does in an adventure game with no forces acting on an agent.
     
  20. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    I think that if in the previous frame the agent
    hasPath
    , and in the current frame it does not
    hasPath
    , then it is considered to have reached it's current destination.
    Some sort of event could easily be thrown when the bool is flipped so you don't need to check it every frame nor keep track of the previous frame state, but I guess that's just how life goes.
     
  21. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    This really should be changed to be event based, just as the new input system did change it to.

    pseudo code:

    Code (CSharp):
    1. navMeshAgent.OnDestinationReached += YourMethod;
     
    Last edited: Jan 12, 2022
  22. TonyTheFox

    TonyTheFox

    Joined:
    Mar 27, 2022
    Posts:
    1
    Ghosthowl and CarterG81 like this.
  23. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    My solution is, it is freaking convoluted, i dont fully understand it myself anymore, but works somehow: ( the solution i wrote above would how it should be not how it is)

    Code (CSharp):
    1.    private bool CheckForDestinationReached(float startTime)
    2.     {
    3.         return Time.time - startTime > 1f && agent.pathStatus == NavMeshPathStatus.PathComplete &&
    4.                agent.remainingDistance <= agent.stoppingDistance;
    5.     }
     
  24. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    @Unity_AndyP I know you might not be the right person to fix that but maybe you can forward it to someone at unity to get this to a nicer solution
     
    Unity_AndyP likes this.
  25. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    Its nothing to fix but to read the docs and interpret the AI movement you wish to have.
    I mean if you dont know how to do it properly, then just watch a youtube video where people explain it. Its not that hard ;)
     
  26. juelzsantana123

    juelzsantana123

    Joined:
    Feb 28, 2019
    Posts:
    17
    i completly abandoned using navagent. it has more bugs the more you work with it. for example avoidance and imposible to add navmesh obstacle on top of agent =D
    Instead i am using static method of navmesh to calculate path and CharacterController to move
     
  27. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    Unity is all about making it easy to understand and removing complexity. So I disagree with your opnion.
    Complexity can be hidden behind easy to understand Methods that do exactly what you exepct of them.
     
  28. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    I use it because I still love to take everythign unity gives us. And it works its just not beautiful in its current form..
     
    juelzsantana123 likes this.
  29. juelzsantana123

    juelzsantana123

    Joined:
    Feb 28, 2019
    Posts:
    17
    i can share code from my system if you will have desire to use something else. in my version units not able to push each other. and you can body block unit. its part of mechanic that is in my game.

    Code (CSharp):
    1.    public static bool CalculatePath(this NavMeshPath navMeshPath, Vector3 start, Vector3 end, int mask, out float lenSqr)
    2.   {
    3.     lenSqr = 0f;
    4.     if (NavMesh.CalculatePath(start, end, mask, navMeshPath) && navMeshPath.corners.Length > 1 && navMeshPath.status == NavMeshPathStatus.PathComplete)
    5.     {
    6.       for (int i = 1; i < navMeshPath.corners.Length; i++)
    7.       {
    8.         lenSqr += (navMeshPath.corners[i - 1] - navMeshPath.corners[i]).sqrMagnitude;
    9.       }
    10.     }
    11. //lenSqr is path length to power of 2. 0.5f is minimal path length
    12.     return lenSqr > 0.5f;
    13.   }
    14.  
    and you also have to ensure that start and end vector3 values are on navmesh. The way i do it is
    NavMesh.SamplePosition(start, out NavMeshHit startPositionHit, 10f, NavMesh.AllAreas) && NavMesh.SamplePosition(end, out NavMeshHit endPositionHit, 10f, NavMesh.AllAreas)

    Using this path you can move character controller and add navmesh obstacle to it and it will still work. Consider that corner[0] is start position so you have to move to corner[1] right away
     
    Last edited: Jan 20, 2023
  30. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    Thanks thanks my code works for us aswell :) ( just dont forget that code can be beautiful and easy too @Unity)
     
    juelzsantana123 likes this.
  31. unity_028AE3B1F1BC5DECE8AD

    unity_028AE3B1F1BC5DECE8AD

    Joined:
    Jul 31, 2022
    Posts:
    94
    Truth is most people do not help others here out "the kindness of their hearts", but for the "holier-than-thou" attitude and kick they get from belittling someone asking for help. In most cases it would be suffice to say "You could look here and it would help", but that doesn't bring the same thrill and dopamine rush as an uppity post does.
     
  32. Saeed-Barari

    Saeed-Barari

    Joined:
    Jul 12, 2021
    Posts:
    56
    for anyone still following up on this thread, the simple and final solution is simply to check the distance and compare it to a desired value for what you considered as 'reached'. If you want, you can use the navmesh's own properties for that:
    Code (CSharp):
    1. if (_agent.remainingDistance <= _agent.stoppingDistance) {
    2.     // reached
    3. }
    or just sample the distance yourself with your own algorithm and compare it with your custom stopping distance:

    Code (CSharp):
    1. if (CalculateDistance() <= CalculateStopingDistance()) {
    2.     // reached
    3. }
    and of course you could turn it into an event-based structure, but I highly recommend you not to go down that path, since navmesh is usually used in state machine patterns, and that means you'd need to take the current state in mind in every event, and that can turn very messy very fast. you can just stick to checking the condition once every few frames and call it a day.
    thanks for reading.
     
    DavidZobrist likes this.