- Home /
How can I tell when a navmeshagent has reached its destination?
Looked in the documentation and couldn't find a somewhat simple solution that A* had. Is there a OnComplete() event or do I have to make one by determining remaining distance?
Answer by Battleb · Oct 24, 2012 at 12:42 AM
I use this: float dist=agent.remainingDistance; if (dist!=Mathf.infinite && agent.pathStatus==NavMeshPathStatus.completed && agent.remainingDistance==0) //Arrived.
You may want to check a few other conditions (pathInvalid, etc.)
Using only the distance have problems if there is another NavAgent with greater avoidance priority in the destination. This leads to your NavAgent to stay still but never arrive. It is an easy case to detect with the current API and you have to create special cases depending on your game, for example, if my agent is in the same position for a while, then maybe it can't reach the destination.
Using .remainingDistance is bad! Please save you self some trouble and read this article.
Be careful, this is a polling based solution, not even driven like OnComplete() which is a much better approach.
Answer by Tryz · Jul 11, 2014 at 04:59 PM
You have to be careful. A distance check isn't always accurate since the steering behavior portion of the NavMeshAgent may actually still be working even if the distance is less than the stopping distance.
I found this worked best for me:
// Check if we've reached the destination
if (!mNavMeshAgent.pathPending)
{
if (mNavMeshAgent.remainingDistance <= mNavMeshAgent.stoppingDistance)
{
if (!mNavMeshAgent.hasPath || mNavMeshAgent.velocity.sqrMagnitude == 0f)
{
// Done
}
}
}
Thanks, Tryz!!! That worked much better in comparison with Battleb answer
Hi @Tryz, sometimes inner most if statement executes 2 times, so target variable value increments 2 times consecutively.
if (!mNav$$anonymous$$eshAgent.pathPending)
{
if (mNav$$anonymous$$eshAgent.remainingDistance <= mNav$$anonymous$$eshAgent.stoppingDistance)
{
if (!mNav$$anonymous$$eshAgent.hasPath || mNav$$anonymous$$eshAgent.velocity.sqr$$anonymous$$agnitude == 0f)
{
// Done
Debug.Log("Executes 2 times");
if(targetPoint >= points.Length - 1) { // if it's a last point
targetPoint = 0;
}
else {
targetPoint++;
}
}
}
}
Any help would be appreciated.
This works if its in the Update function, but im trying to avoid making calculation every frame. Is there a way to Run a piece of code ONLY when the agent reaches the destination? thanks!
You could create a Coroutine with this code inside and call it at the moment you set the desired position to move. (I know the question is old but it might be a useful hint for others)
Answer by JimRustler · Oct 03, 2014 at 09:12 AM
In the Unity Documentation it says that remainingDistance is "The distance between the agent's position and the destination on the current path". I kept getting a zero for remaining distance so my workaround pathcomplete function was a bit different
protected bool pathComplete()
{
if ( Vector3.Distance( m_NavAgent.destination, m_NavAgent.transform.position) <= m_NavAgent.stoppingDistance)
{
if (!m_NavAgent.hasPath || m_NavAgent.velocity.sqrMagnitude == 0f)
{
return true;
}
}
return false;
}
I was having the same prople JimRustler. Thanks for this version. Simple and leaves nothing to chance.
You should use remainingDistance. Vector3.distance just draws a straight line between the 2 objects and calculates the distance.
When there's a wall between the 2 for example, Vector3.distance is no longer accurate.
Answer by Billu · Mar 25, 2016 at 11:21 AM
One way to implement this mechanism is to place a GameObject on the destination (you probably used one as destination already), and add BoxCollider and a trigger. Once the object with the nav mesh agent collided with the destination game object, you can determine in the OnTriggerEnter()
function and check if the colliding object is the one you want (use tag or name), and do your rest stuff.
Of course, you can attach a script on the destination object, so it will become transparent on game start, so no one would see them.
yes that certainly is one way. I have been doing that for some time now but it feels like such a hack to me( I am a noob) so I was looking for simply ( or not so simply) telling the navmesh agent that it has reached its stopping DIstance so ...stop this animation and start another. Sounds easy when I say it but can't get it to work at all. Nor can I get ANY of the solutions on this page to work. is this java or what? I get errors on all sorts of stuff. why can't it be as simple as "if( remaingDistance ==0){ animation .Play("whatever")
@Billu $$anonymous$$y units now patrolling. And if another enemy unit comes into their predefined range - while they patrol - I want them to automatically attack them. Would It be a good idea to solve this also with a Collider
? I mean to have 2 Collider
on the gameObject
. One for it's aggro-range, and another one to deter$$anonymous$$e how close the unit has to get to attack the target?
Answer by justinl · Oct 14, 2012 at 04:14 AM
This isn't much of an answer, but for other people who have the same question, yes Brenden you are correct. You'll need to write your own. It might also be worth noting that sometimes myAgent.remainingDistance is not always accurate or available, so you may need to resort to using Vector3.Distance() as a backup.
Your answer
Follow this Question
Related Questions
How do I limit the path of a NavMeshAgent? 0 Answers
Finding Closest Object Through Navmesh,Identifying Which Object Is Closest on NavMesh 0 Answers
Instantiated objects at beginning of runtime are messing with the pathing for my NavMesh. 0 Answers
Is it possible to have a navmesh agent that ignores obstacles? 1 Answer
Which NavMeshSurface is a point (already on the NavMesh) on? 0 Answers