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

C# Getting a Vector 2 from an angle

Discussion in 'Scripting' started by Ultermarto, Oct 14, 2014.

  1. Ultermarto

    Ultermarto

    Joined:
    May 10, 2013
    Posts:
    31
    Hey. So basically I'm trying to work out how I can take the rotation of my character and express it as a Vector2. This way, I can use the Vector2 to tell the AddForce function which way to launch my character when it bounces. The result I want is a character which bounces whichever way it is rotated.

    AddForce takes a vector input, but from what I can tell, Unity doesn't store angles in the same kind of way, so using these angles as an input wouldn't give me the results I want. I know a little about maths and I'm pretty sure I know how to get around this problem.

    1. My character's rotation is given as an angle (e.g 90 degrees, 45 degrees).
    2. The sin function should return the ratio between the length of the hypotenuse, and the opposite side, of a right-angle triangle formed by my character's angle of rotation. For example, if my character was facing 45 degrees, it would form a right-angle triangle with two equal sides. The sin function tells me that the ratio between the opposite side and the hypotenuse is around 0.7.
    3. I can create a normalized vector from these numbers pretty easily. All I need to do is find the undescribed (adjacent) side of the triangle, which is the square root of (Hyponetuse^2 - Opposite^2). Then I have my two values to make a vector out of.

    I could do this, except for the fact that Unity's sin function returns the angle in radians, which I don't really understand. I've checked with my calculator, and the sin function there returns a different value than Unity's sin function, meaning that I don't know how to use it in the same way. So, I could use some explanation. Either that or someone could suggest me a whole other method, though I'd rather not touch Quaternions since I don't understand those either.
     
    Last edited: Oct 14, 2014
  2. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Can;t you just use transform.forward?

    To convert radians to degrees, multiply by Mathf.rad2deg
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    2pi radians == 360 degrees

    It's just a different scale.

    Degrees breaks an angle into 360 discrete units. This value is sort of arbitrary really.

    Where as radians is based on the circumference of a circle with radius 1 (a unit circle). This allows it to be more useful in maths.

    Note, your calculator (if it's a scientific calculator or better) should have modes where you can change it between degrees and radians. Usually in the upper left there is a button that says "DEG" and another that says "RAD" (they may be the same button and you have to push the alt button as well).



    Now, from an angle you can get a vector as you described. BUT there's an issue. An angle doesn't contain as much information as a vector... to get a 2 dimensional vector you need to inject information. This information is implied when dealing with angles. That being 0 is some direction, and we measure off that direction. So if you calculate some vector as:

    <cos(angle), sin(angle)>

    You'll get the vector rotated by the angle off of <1,0>. If you instead do something like:

    <sin(angle>, cos(angle)>

    You'll get the vector rotated by the angle off of <0,1>.

    You could even rotate some arbitrary vector by some angle:

    Code (csharp):
    1.  
    2.         /// <summary>
    3.         /// Rotate Vector2 clockwise by 'a'
    4.         /// </summary>
    5.         /// <param name="v"></param>
    6.         /// <param name="a"></param>
    7.         /// <returns></returns>
    8.         public static Vector2 RotateBy(Vector2 v, float a, bool bUseRadians = false)
    9.         {
    10.             if (!bUseRadians) a *= Mathf.Deg2Rad;
    11.             var ca = Math.Cos(a);
    12.             var sa = Math.Sin(a);
    13.             var rx = v.x * ca - v.y * sa;
    14.                        
    15.             return new Vector2( (float)rx, (float)(v.x * sa + v.y * ca));
    16.         }
    17.  
    Here, I'll share with you a collection of vector math methods:

    Code (csharp):
    1.  
    2. #region Vector2 Trig
    3.  
    4.         /// <summary>
    5.         /// Get the angle in degrees off the forward defined by x.
    6.         /// </summary>
    7.         /// <param name="v"></param>
    8.         /// <returns></returns>
    9.         public static float Angle(Vector2 v)
    10.         {
    11.             return Mathf.Atan2(v.y, v.x) * Mathf.Rad2Deg;
    12.         }
    13.        
    14.         /// <summary>
    15.         /// Get the angle in degrees off the forward defined by x.
    16.         /// </summary>
    17.         /// <param name="x"></param>
    18.         /// <param name="y"></param>
    19.         /// <returns></returns>
    20.         public static float Angle(float x, float y)
    21.         {
    22.             return Mathf.Atan2(y, x) * Mathf.Rad2Deg;
    23.         }
    24.  
    25.         public static float AngleBetween(Vector2 a, Vector2 b)
    26.         {
    27.             return Mathf.Acos(Vector2.Dot(a, b) / (a.magnitude * b.magnitude)) * Mathf.Rad2Deg;
    28.         }
    29.  
    30.         public static void Reflect(ref Vector2 v, Vector2 normal)
    31.         {
    32.             var dp = 2f * Vector2.Dot(v, normal);
    33.             var ix = v.x - normal.x * dp;
    34.             var iy = v.y - normal.y * dp;
    35.             v.x = ix;
    36.             v.y = iy;
    37.         }
    38.  
    39.         public static Vector2 Reflect(Vector2 v, Vector2 normal)
    40.         {
    41.             var dp = 2 * Vector2.Dot(v, normal);
    42.             return new Vector2(v.x - normal.x * dp, v.y - normal.y * dp);
    43.         }
    44.  
    45.         /// <summary>
    46.         /// Rotate Vector2 clockwise by 'a'
    47.         /// </summary>
    48.         /// <param name="v"></param>
    49.         /// <param name="a"></param>
    50.         /// <returns></returns>
    51.         public static Vector2 RotateBy(Vector2 v, float a, bool bUseRadians = false)
    52.         {
    53.             if (!bUseRadians) a *= Mathf.Deg2Rad;
    54.             var ca = Math.Cos(a);
    55.             var sa = Math.Sin(a);
    56.             var rx = v.x * ca - v.y * sa;
    57.                        
    58.             return new Vector2( (float)rx, (float)(v.x * sa + v.y * ca));
    59.         }
    60.  
    61.         /// <summary>
    62.         /// Rotate Vector2 clockwise by 'a'
    63.         /// </summary>
    64.         /// <param name="v"></param>
    65.         /// <param name="a"></param>
    66.         public static void RotateBy(ref Vector2 v, float a, bool bUseRadians = false)
    67.         {
    68.             if (!bUseRadians) a *= Mathf.Deg2Rad;
    69.             var ca = Math.Cos(a);
    70.             var sa = Math.Sin(a);
    71.             var rx = v.x * ca - v.y * sa;
    72.  
    73.             v.x = (float)rx;
    74.             v.y = (float)(v.x * sa + v.y * ca);
    75.         }
    76.  
    77.         /// <summary>
    78.         /// Rotates a vector toward another. Magnitude of the from vector is maintained.
    79.         /// </summary>
    80.         /// <param name="from"></param>
    81.         /// <param name="to"></param>
    82.         /// <param name="a"></param>
    83.         /// <param name="bUseRadians"></param>
    84.         /// <returns></returns>
    85.         public static Vector2 RotateToward(Vector2 from, Vector2 to, float a, bool bUseRadians = false)
    86.         {
    87.             //var angleBetween = Mathf.Acos(Vector2.Dot(from, to) / (from.magnitude * to.magnitude));
    88.             //if (!bUseRadians) a *= Mathf.Deg2Rad;
    89.             //var t = angleBetween / a;
    90.             //return Slerp(from, to, t);
    91.  
    92.             if (!bUseRadians) a *= Mathf.Deg2Rad;
    93.             var a1 = Mathf.Atan2(from.y, from.x);
    94.             var a2 = Mathf.Atan2(to.y, to.x);
    95.             a2 = MathUtil.NormalizeAngleToAnother(a2, a1, true);
    96.             var ra = (a2 - a1 >= 0f) ? a1 + a : a1 - a;
    97.             var l = from.magnitude;
    98.             return new Vector2(Mathf.Cos(ra) * l, Mathf.Sin(ra) * l);
    99.         }
    100.  
    101.         public static Vector2 RotateTowardClamped(Vector2 from, Vector2 to, float a, bool bUseRadians = false)
    102.         {
    103.             if (!bUseRadians) a *= Mathf.Deg2Rad;
    104.             var a1 = Mathf.Atan2(from.y, from.x);
    105.             var a2 = Mathf.Atan2(to.y, to.x);
    106.             a2 = MathUtil.NormalizeAngleToAnother(a2, a1, true);
    107.  
    108.             var da = a2 - a1;
    109.             var ra = a1 + Mathf.Clamp(Mathf.Abs(a), 0f, Mathf.Abs(da)) * Mathf.Sign(da);
    110.  
    111.             var l = from.magnitude;
    112.             return new Vector2(Mathf.Cos(ra) * l, Mathf.Sin(ra) * l);
    113.         }
    114.  
    115.         /// <summary>
    116.         /// Angular interpolates between two vectors.
    117.         /// </summary>
    118.         /// <param name="from"></param>
    119.         /// <param name="to"></param>
    120.         /// <param name="t"></param>
    121.         /// <returns>The vectors are 2 dimensional, so technically this is not a spherical linear interpolation. The name Slerp is kept for consistency.
    122.         /// The result would be if you Slerped between 2 Vector3's that had a z value of 0. The direction interpolates at an angular rate, where as the
    123.         /// magnitude interpolates at a linear rate.</returns>
    124.         public static Vector2 Slerp(Vector2 from, Vector2 to, float t)
    125.         {
    126.             var a = MathUtil.NormalizeAngle(Mathf.Lerp(Mathf.Atan2(from.y, from.x), Mathf.Atan2(to.y, to.x), t), true);
    127.             var l = Mathf.Lerp(from.magnitude, to.magnitude, t);
    128.             return new Vector2(Mathf.Cos(a) * l, Mathf.Sin(a) * l);
    129.         }
    130.  
    131.         public static Vector2 Orth(Vector2 v)
    132.         {
    133.             return new Vector2(-v.y, v.x);
    134.         }
    135.  
    136.         #endregion
    137.  
    Found:
    https://code.google.com/p/spacepupp.../SpacepuppyUnityFramework/Utils/VectorUtil.cs
     
    isotian likes this.
  4. Ultermarto

    Ultermarto

    Joined:
    May 10, 2013
    Posts:
    31
    Apparently I can. Thanks.

    Code (CSharp):
    1. Mathf.sin(45) * Mathf.Rad2Deg
    still returns a different value, 48.75, than my calculator, which returns 0.71. I believe the latter is the value I'd need to create the correct vector, so unfortunately your suggestion doesn't seem to work. At least I learned a lot about trigonometry in the last hour...
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    Code (csharp):
    1.  
    2. Mathf.sin(45) * Mathf.Rad2Deg
    3.  
    Mathf.sin does NOT return radians.

    The sine function takes in an angle and returns the length of the leg opposite of that angle if it were an angle on a right triangle with hypotenuse length 1.

    You want:

    Code (csharp):
    1.  
    2. var y = Mathf.Sin(45f * Mathf.Deg2Rad);
    3.