Detecting if a NavMeshAgent is rotating

Hey,

I am using NavMeshAgents for my AI characters in my game and I am just implementing the animations for them at the moment. I am using the velocity property to check if they are moving or not and blending the idle, run and walk animations using that. However, I am not sure how I can then blend my turning left or right animations. Is there a way to detect if the NavMeshAgent is rotating?

Thanks for any help in advance

If you’re using a rigidbody you can get the sqrMagnitude of the angularVelocity and check if it’s greater than 0. Otherwise you’ll need to keep track of your own angular velocity.

public bool IsRotating { get { return myRigidbody.angularVelocity.sqrMagnitude > 0.0f; } }

The answer to “can I do this with a NavmeshAgent” is “no” 99% of the time.

You’ll have to calculate the rotation yourself:

void Update() {
    Vector3 currentFacing = transform.forward;
    currentAngularVelocity = Vector3.Angle(currentFacing, lastFacing) / Time.deltaTime; //degrees per second
    lastFacing = currentFacing;

    isRotating = currentAngularVelocity > 1f; //or whatever treshold you find appropriate
}

@jimroberts : using a navmesh agent and a non-kinematic rigidbody on the same object is not a good idea. The rigidbody will try to move the object with physics every frame, and the navmesh agent will snap it back to where it believes it should be. I had a rigidbody’s velocity.y register as minus several thousand for an object that stood still.

3 Likes

Thanks for the comments guys.

I managed to get something working like this -

Vector3 s = mAgent.transform.InverseTransformDirection(mAgent.velocity).normalized;
        float speed = s.z;
        float turn = s.x;
        mAnimator.SetFloat(mSpeedHash,speed );
        mAnimator.SetFloat(mTurnHash, turn);

Basically, take the velocity vector put it into the models local space. Then use the z as a forward movement ratio and turn as the x. This is assumes that the model is aligned with forward and backwards being the z.

I normalize this and chuck it into my animation blend.

13 Likes

Thank you thank you thank you. I’ve been searching for this and finally found it. It works (:

float PreviousRotation;
public void Update()
{
if(PreviousRotation != transform.rotation.y)
{
Action();
}
PreviousRotation =transform.rotation.y;
}

float rotation;
float currentAngularVelocity;
void Turning()
{

Vector3 s = agent.transform.InverseTransformDirection(agent.velocity).normalized;
currentAngularVelocity = Mathf.Lerp(currentAngularVelocity, s.x,Time.deltaTime);

if (currentAngularVelocity > 0.1F) rotation = Mathf.Lerp(rotation, 1,Time.deltaTime);
else if (currentAngularVelocity < -0.1F) rotation = Mathf.Lerp(rotation, -1, Time.deltaTime);
else rotation = 0;

animator.SetFloat(“TurnOnSpotDirection”, rotation);

}