Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

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,199
    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:
    368
    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);

    }