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. Dismiss Notice

Rotating to a set direction using an animation

Discussion in 'Animation' started by BenS_UK, Jan 17, 2016.

  1. BenS_UK

    BenS_UK

    Joined:
    Jan 5, 2016
    Posts:
    7
    Hi,

    I feel like I'm missing something obvious here but I'm really struggling to rotate a character to a specified rotation around the Y Axis using an animation.

    So I have a rotating animation which uses a parameter called Rotate (referenced through m_HashRotationParam), which goes between -1 (Anticlockwise) and +1 (Clockwise)
    I have tested this with the key inputs and it works correctly.

    What I'm now trying to do is rotate based on a pre-defined end point, so given the end location the character needs to get to rotate them to face that way using the animation.

    I've got as far as the below which gives me my position to move to but I can't work out what test to do to get the Angle between the current forward position and the angle with the move too.
    I tried Vector3.Angle but it gives an absolute value and it also does so around all 3 axis not just Y.
    Code (CSharp):
    1.  
    2.    public void SetMoveTo (Vector3 moveTo) {
    3.  
    4.         //moveTo is the position in space the avatar should turn to face around their Y axis
    5.  
    6.         if (//Test here to see which way should turn) {
    7.             m_CharAnimator.SetFloat (m_HashRotationParam, -1.0f, 0.0f, Time.deltaTime);
    8.         } else {
    9.             m_CharAnimator.SetFloat (m_HashRotationParam, 1.0f, 0.0f, Time.deltaTime);
    10.         }
    11.  
    12.  
    13.     }

    I suspect I may be trying to do something that Unity will handle for me but haven't been able to see anything in the Navigation, Graphics or Animations sections which helps me.

    Any help would be really appreciated, either fixing this specific challenge or pointing me in the direction of how I should be approaching this!

    Thanks
    Ben
     
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Maybe be a bit simple and...
    Code (CSharp):
    1. float angle = Vector2.Angle(new Vector2(forward.x,forward.z),new Vector2(target.x,target.z));
    That's rotation difference between vectors around one axis Y.
    Why solve 2D problems in 3D space? ;)
     
  3. BenS_UK

    BenS_UK

    Joined:
    Jan 5, 2016
    Posts:
    7
    Thanks Teravisor, that is a great call to simplify things and definitely helps my head.

    Unfortunately I don't think it helps me to know whether I need to rotate clockwise or counter-clockwise (which the animation uses) because I get the absolute angle which is always < 180degs so if I get an angle of 90 returned it could be 90degs cw or 90degs ccw.
    What I would really like to know is it 90 / -90 or 90 / 270?

    Any thoughts on how I distinguish?

    Thanks
    Ben
     
  4. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Let me dig my support lib... Those methods are far from good, pretty or fast, but seem to work for me.
    Code (CSharp):
    1.  
    2. /// <summary>
    3.     /// Angle between vector (1,0) and specified vector in (0,2*pi) radians. Just don't pass Vector2(0,0).
    4.     /// </summary>
    5. public static float AngleFromVector2(Vector2 vector)
    6.     {
    7.         return Mathf.Atan2(vector.y, vector.x);
    8.     }
    9.  
    10. /// <summary>
    11. /// Returns shortest angle between two angles in radians. Negative means clockwise, positive means counterclockwise.
    12. /// </summary>
    13. public static float ShortestAngleBetween(float anglestart,float anglefinish)
    14.     {
    15. //Normalizing angles to [0;2*PI)
    16.         while (anglestart < 0) anglestart += Mathf.PI * 2;
    17.         while (anglestart >= Mathf.PI * 2) anglestart -= Mathf.PI * 2;
    18.         while (anglefinish < 0) anglefinish += Mathf.PI * 2;
    19.         while (anglefinish >= Mathf.PI * 2) anglefinish -= Mathf.PI * 2;
    20.         //Measuring distance in clockwise and counterclockwise directions
    21.         float counterClockwiseDistance;//Counterclockwise
    22.         float clockwiseDistance;//Clockwise
    23.         if (anglefinish < anglestart)
    24.         {
    25.             clockwiseDistance = anglestart - anglefinish;
    26.             counterClockwiseDistance = Mathf.PI * 2 - anglestart + anglefinish;
    27.         }
    28.         else
    29.         {
    30.             clockwiseDistance = Mathf.PI*2 - anglefinish + anglestart;
    31.             counterClockwiseDistance = anglefinish - anglestart;
    32.         }
    33.         if (counterClockwiseDistance < clockwiseDistance) return counterClockwiseDistance;
    34.         else return -clockwiseDistance;
    35.     }
    Now use them like ShortestAngleBetween(AngleFromVector2(...),AngleFromVector2(...));

    Don't know if they're bugfree, but they did work in my previous project.

    There are certainly better solutions out there if you google.;)
     
  5. BenS_UK

    BenS_UK

    Joined:
    Jan 5, 2016
    Posts:
    7
    Thank you Teravisor, really appreciate your input.

    I struggled searching, didn't seem to quite get the right description for what I was after so this is really useful.

    Cheers
    Ben