Search Unity

Detecting if a NavMeshAgent is rotating

Discussion in 'Scripting' started by Korno, Jun 10, 2016.

  1. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    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
     
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    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.

    Code (CSharp):
    1. public bool IsRotating { get { return myRigidbody.angularVelocity.sqrMagnitude > 0.0f; } }
     
    Last edited: Jun 10, 2016
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    The answer to "can I do this with a NavmeshAgent" is "no" 99% of the time.

    You'll have to calculate the rotation yourself:

    Code (csharp):
    1. void Update() {
    2.     Vector3 currentFacing = transform.forward;
    3.     currentAngularVelocity = Vector3.Angle(currentFacing, lastFacing) / Time.deltaTime; //degrees per second
    4.     lastFacing = currentFacing;
    5.  
    6.     isRotating = currentAngularVelocity > 1f; //or whatever treshold you find appropriate
    7. }
    @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.
     
    Ghosthowl, myloran and Taloose like this.
  4. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    Thanks for the comments guys.

    I managed to get something working like this -

    Code (CSharp):
    1. Vector3 s = mAgent.transform.InverseTransformDirection(mAgent.velocity).normalized;
    2.         float speed = s.z;
    3.         float turn = s.x;
    4.         mAnimator.SetFloat(mSpeedHash,speed );
    5.         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.
     
  5. pedrociva

    pedrociva

    Joined:
    Sep 27, 2019
    Posts:
    2
    Thank you thank you thank you. I've been searching for this and finally found it. It works :)
     
  6. Mohey_Al-Deen

    Mohey_Al-Deen

    Joined:
    Apr 18, 2018
    Posts:
    1
    float PreviousRotation;
    public void Update()
    {
    if(PreviousRotation != transform.rotation.y)
    {
    Action();
    }
    PreviousRotation =transform.rotation.y;
    }
     
  7. WILEz1975

    WILEz1975

    Joined:
    Mar 23, 2013
    Posts:
    375
    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);

    }