- Home /
Vector2.Angles Direction
Hi,
I'm trying to calculate the angle between two points like this:
float ang = Vector2.Angle(new Vector2(-1,0), new Vector2(0,1));
It returns 90, it's ok, but if I invert the points like this:
float ang = Vector2.Angle(new Vector2(0,1), new Vector2(-1,0));
It returns 90 instead 270.
The question is, if I have a FROM and a TO Vector2 point, why it calculates the smallest angle instead the angle of the points in counter-clockwise?
Thanks and sorry for my poor english. Borgo
Answer by Sigil · Sep 01, 2011 at 05:40 AM
I think Peter is right with the way Vector2.Angle is working: It is doing a dot product between the two vectors, and this can only tell you the angle from 0 to 180 just like he said. You can use a cross product between the two vectors (as Vector3s with a z value of 0) to determine which direction the angle is heading. Try this:
Vector2 fromVector2 = new Vector2(0, 1);
Vector2 toVector2 = new Vector2(-1, 0);
float ang = Vector2.Angle(fromVector2, toVector2);
Vector3 cross = Vector3.Cross(fromVector2, toVector2);
if (cross.z > 0)
ang = 360 - ang;
Debug.Log(ang);
I think this will work for any two vectors.
Edit: Updated to use the implicit cast.
Thanks Sigil, it works perfectly!! I just modify the cross.z>0 to cross.z<0 cause (I guess) the default angle direction is counter-clockwise
Just for the sake of saving writing, you can cast from Vector2 to Vector3 implicitly. You can pass the two vector2's directly into Vector3.Cross() and save yourself the time of creating a new vector3 explicitly.
Answer by Peter G · Sep 01, 2011 at 12:31 AM
One guess is that its easier to keep things straight if you clamp angles between 0 and 180 degrees. Then you can express every angle from one side or the other. You can figure out which side your angle is with cross products. There's a forum thread on it somewhere.
I also have some speculation as to why this is. This is a guess because I don't know how the function works internally, but I guess it uses an inverse trig function. I'm not sure which one, but I'd use arccos because its principle domain is from 0 to 180 degrees.
arccos ( (V1 • V2) / ( |V1| |V2|) ) = Angle.
Since arccos is defined from 0 to 180, the only values it can return are from 0 to 180.
Note: that is just speculation. I would be interested to here how Vector2.Angle() actually works
Thanks Peter, that is it, Sigil have posted the "Cross Product".
Just because you ask for it, this is how Vector3.Angle is defined:
public static float Angle(Vector3 from, Vector3 to)
{
return $$anonymous$$athf.Acos($$anonymous$$athf.Clamp(Vector3.Dot(from.normalized, to.normalized), -1f, 1f)) * 57.29578f;
}
ps just in case it's not obvious 57.29578f == (180/PI) to convert radians to degree.
pps: the function looks exactly the same for Vector2
Answer by Varaughe · Apr 25, 2015 at 12:40 PM
CAN someone explain to me why in Unity : Vector2.Angle(new Vector2 (1, 1),new Vector2 (1, 1)) is NOT 0 ??
WHY IS IT 0.01978234 ??????????????????
Floating point numbers on computers only have a limited amount of accuracy, which can introduce errors which can accumulate over multiple operations. You should never test a floating point number (A Vector2 is just two floats) against an absolute value, since there's a high chance that it'll be ever so slightly off.
When testing equality between floating-point numbers, you'll want to use $$anonymous$$athf.Approximately(valueA, valueB), which will return true if the values are within a small range. Although sometimes this won't be enough, so the other solution is to do something like this, which allows you to control the precision:
if ($$anonymous$$athf.Abs(valueA - valueB) < someSmallValue)
{
// Do the thing
}
Here's a video that explains floating point precision errors at more length if you're interested: https://www.youtube.com/watch?v=PZRI1IfStY0
Answer by jakobschou · May 14, 2017 at 07:21 PM
Here is another alternative:
float Angle( Vector2 a, Vector2 b ) {
var an = a.normalized;
var bn = b.normalized;
var x = an.x * bn.x + an.y * bn.y;
var y = an.y * bn.x - an.x * bn.y;
return Mathf.Atan2(y, x) * Mathf.Rad2Deg;
}