How To Know If NavMeshAgent Is Moving

Hi there,
Occasionally, when using a NavMeshAgent on a NavMesh, the player stops moving because he is blocked from completing his move to setDestination(). At this point, the player’s animation remains walking, however, I would like it to set to idle at this point.

How can I find out if a navMeshAgent is not physically moving but the animation walk is still active? Or something along these lines.

1 Like

Check how far the NavMeshAgent moved since the last frame. Like that you can compute the speed. If it is below a certain value, you play the idle animation, otherwise the walk animation.

1 Like

This probably does that for you - http://docs.unity3d.com/ScriptReference/NavMeshAgent-velocity.html

Could also check how much this has changed to tell if the agent has moved - http://docs.unity3d.com/ScriptReference/NavMeshAgent-remainingDistance.html

6 Likes

I expected that someone who has more than 5000 posts is able to read the documentation before posting, that’s why I didn’t check it :slight_smile:

1 Like

Fair point. I checked for my own curiosity because I didn’t know - and I only have 3000 posts :slight_smile:

1 Like

Yah yah yah.
Merci boucoup!
I do appreciate.

2 Likes

I cant seem to get it to work. I hate Mondays.

I have tried comparing lastPos to currentPos, remaingDistance to lastRemainingDistance and if velocity is 0. All catch a point in a path where this is true, despite it not being the desired effect. The result is a moving agent, with an idle animation.

Line 22 should be the point of interest.

        ///TAP FOR MOVE  
        if(Input.GetMouseButtonDown(0)){
              Ray ray = Cam_Main.ScreenPointToRay(new Vector3(Input.mousePosition.x, Input.mousePosition.y + 7.1f, -18.6f));
              Vector3 dir = new Vector3(ray.direction.x * 100, ray.direction.y * 100, ray.direction.z * 100);
            RaycastHit hit;
            if(Physics.Raycast(ray.origin, dir, out hit, groundsLayerMask)){  
                moveToPos = hit.point;//new Vector3(hit.point.x, hit.point.y, agent.transform.position.z);
                dist = Vector3.Distance(agent.transform.position, moveToPos);
                agent.SetDestination(moveToPos);
                agentAnimator.SetFloat("Speed",0.2f);//make anim move
                movementActive = true;
              }
        }
      
        if(movementActive){
            dist = Vector3.Distance(agent.transform.position, moveToPos);
            if(dist < 0.02f){
                agentAnimator.SetFloat("Speed",0f);//make anim move
                movementActive = false;
            }
            if(lastDist == dist && agent.velocity.x == 0 && agent.velocity.z == 0){
                agentAnimator.SetFloat("Speed",0f);//make anim move
                movementActive = false;
            }
          
            lastDist = dist;
        }
1 Like

Some ppl are about quantity :wink:

2 Likes

You don’t need movementActive from my point of view.

float velocity = agent.velocity.magnitude;
if (velocity > someMovementSpeedThatMakesSense) {
    agentAnimator.SetFloat("Speed",0.2f);
} else {
    agentAnimator.SetFloat("Speed,0f);
}

Like that you can get rid of everything after line 16, as well as 11 and 12.

3 Likes

thanks, just randomly looked for a solution to animate a character and this fixed all the problems i had.

1 Like

User Tryz posted a thorough solution here that takes path existence, proximity and velocity into account:
https://answers.unity.com/questions/324589/how-can-i-tell-when-a-navmesh-has-reached-its-dest.html?childToView=746157#answer-746157

Their code:

 // Check if we've reached the destination
if (!mNavMeshAgent.pathPending)
{
     if (mNavMeshAgent.remainingDistance <= mNavMeshAgent.stoppingDistance)
     {
         if (!mNavMeshAgent.hasPath || mNavMeshAgent.velocity.sqrMagnitude == 0f)
         {
             // Done
         }
     }
}
5 Likes

Maybу it is easier to use just Math.Abs(agent.velocity.x + agent.velocity.y + agent.velocity.z) < .05?

2 Likes

You guys made my life easier.

agent.velocity.sqrMagnitude > 0