Search Unity

Vector to Angle function

Discussion in 'Scripting' started by flim, Jun 6, 2011.

  1. flim

    flim

    Joined:
    Mar 22, 2008
    Posts:
    326
    Is there a way to calculate the Euler angle based on a vector?

    In another engine there is a vec_to_angle(Angle *ang, Vector *dir) function to return the pan and tilt of an Euler angle.
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Yes, it is called Vector3.Angle, and it works on the premise that one vector is based on another vector in a zero world environment.

    This means that Vector3.Angle(transform.forward, transform.InverseTransformPoint(target.position)); would give you the angle from the forward direction to the localized position of a target point.

    Observe code:
    Code (csharp):
    1.  
    2. //overall angle from the forward direction
    3. var angle=Vector3.Angle(transform.forward, transform.InverseTransformPoint(target.position));
    4.  
    5. // angle aligned to the X/Z plane (With a Dot gauging if it is positive or negative)
    6. var angle=Vector3.Angle(transform.forward, Vector3.Scale(transform.InverseTransformPoint(target.position), Vector3(1,0,1));
    7. angle=Vector3.Dot(Vector3.right, transform.InverseTransformPoint(target.position)) >0.0 ? angle : -angle;
    8.  
     
    Rodolfo-Rubens likes this.
  3. flim

    flim

    Joined:
    Mar 22, 2008
    Posts:
    326
    MaxLohMusic likes this.
  4. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    /poke /poke

    I did provide a piece of code that gives you a negative angle... You have to calculate the negative from one of the values. I gave a Vector3.Dot, but you could easily say that if the transform.InverseTransformPoint(target.position).x is negative, so is the angle.

    So in your other code, you would test the joystick's y position and see if it is negative. (since you are testing the angle from the X direction)

    Code (csharp):
    1.  
    2. var turret : Transform;
    3. var joystick : Joystick;
    4. var turnSpeed: float = 500; // Turret movement parameter
    5. private var joystickAngle : float;
    6.  
    7. function Update()
    8. {
    9.     joystickAngle = Vector2.Angle( Vector2(1,0), Vector2(-joystick.position.x, joystick.position.y) );
    10.     joystickAngle = joystick.position.y > 0.0 ? joystickAngle :-joystickAngle;
    11.     Debug.Log(joystickAngle);
    12.     turret.transform.rotation = Quaternion.Slerp(turret.transform.rotation, Quaternion.Euler(Vector3(0, joystickAngle - 90, 0)), turnSpeed * Time.deltaTime);
    13. }
    14.  
     
  5. flim

    flim

    Joined:
    Mar 22, 2008
    Posts:
    326
    The negative y position trick works.
    Will look at the Vector3.Dot code. Thanks so much!
     
    MaxLohMusic likes this.
  6. Joseph-Ferano

    Joseph-Ferano

    Joined:
    Jul 18, 2008
    Posts:
    165
    Another simple way of doing this is with Mathf.Atan2();

    Just takes the X and Y and calculates the angle. Returns a negative and positive number.
     
    PoRtCuLLiS and fadden like this.
  7. flim

    flim

    Joined:
    Mar 22, 2008
    Posts:
    326
    Yes, that works, I can get negative number directly. Thanks so much!
     
  8. DukeOfDesmo

    DukeOfDesmo

    Joined:
    Oct 29, 2008
    Posts:
    67
    For some reason I got this post mixed up with another (similar) question..

    Code (csharp):
    1.  
    2. public float GetYRotFromVec(Vector2 v1, Vector2 v2)
    3. {
    4.    float _r = Mathf.Atan2(v1.x - v2, v1.y - v2.y);
    5.    float _d = (_r / Mathf.PI) * 180;
    6.  
    7.   return _d;
    8.  
    9. }

    so then you can do something like:

    Code (csharp):
    1. float _yRot = GetYRotFromVec(transform.position, target.transform.position);
    2. Quaternion _targetRot  = Quaternion.Euler(0, _yRot, 0);
    I guess you can then slerp between the two.

    Hope this helps!
     
    Radivarig, deab and soumen like this.
  9. flim

    flim

    Joined:
    Mar 22, 2008
    Posts:
    326
    Create a function to pass 2 vectors in really help, never think that before.

    Because the Angle *ang in the vec_to_angle like a vector to store pan and tilt.

    So if I want to have pan, and tilt, should I build separate function for pan and tilt?
     
    Last edited: Jun 7, 2011
  10. Antitheory

    Antitheory

    Joined:
    Nov 14, 2010
    Posts:
    549
    public static float PosNegAngle(Vector3 a1, Vector3 a2, Vector3 n)
    {
    float angle = Vector3.Angle(a1, a2);
    float sign = Mathf.Sign(Vector3.Dot(n, Vector3.Cross(a1, a2)));
    return angle*sign;
    }

    This an all purpose version of the positive-negative angle dilemma. "n" is the normal of the reference plane. For rotations around the Y axis you would use Vector3.up. But there are times when you want to find the pos-neg rotation in different planes.


    PosNegAngle(Vector3.forward,Vector3.right, Vector3.up) =90

    PosNegAngle(Vector3.right, Vector3.forward, Vector3.up)= -90


    PosNegAngle(Vector3.up, Vector3.forward, Vector3.right) = 90

    PosNegAngle(Vector3.forward, Vector3.up, Vector3.right) = -90
     
    pushkar_unity likes this.
  11. Joseph-Ferano

    Joseph-Ferano

    Joined:
    Jul 18, 2008
    Posts:
    165
    Unity also already has a property for that so you don't have to convert the rotation from radians to degrees;

    Code (csharp):
    1. float angle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
     
    Last edited: Jun 7, 2011
    forestrf likes this.
  12. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Would this solve his problem then?

    Code (csharp):
    1.  
    2. float angle = Mathf.Atan2(joystick.position.x, joystick.position.y) * Mathf.Rad2Deg;
    3.  
     
  13. flim

    flim

    Joined:
    Mar 22, 2008
    Posts:
    326
    Yes, that is what I am using now. Thanks everyone for help.:)

    I am thinking how to remake the vec_to_angle function, which return pan and tilt at the same time.
     
  14. Lason

    Lason

    Joined:
    Apr 21, 2011
    Posts:
    2
    You could have it return a vector2, x = pan, y = tilt. Or if you wanted to, you could make a struct that does essentially the same thing.
     
  15. soumen

    soumen

    Joined:
    Jul 8, 2013
    Posts:
    8
    Thanks this helps me solve my problem.