The question is answered, right answer was accepted
Angle between two vectors
How can I obtain the angle between two vectors, for example I have the following:
I know that the angle (in degrees) between A and B1 is 0, but how can I know the angle between A and B2, considering the axis orientation of the gameobject...
Any suggestions?
Why we simply not check is degree above or bellow X axis and simply add 360?
float AngleBetweenVectors(Vector2 a, Vector2 b) {
float degree = $$anonymous$$athf.Atan2(b.y - a.y, b.x - a.x) * $$anonymous$$athf.Rad2Deg;
return (degree > 0) ? degree : 360 + degree;
}
This works fine without extra calculations or even use top as zero degree and then negative degree will work just find with Unity:
private float AngleBetweenVectors(Vector2 a, Vector2 b) {
return -$$anonymous$$athf.Atan2(b.x - a.x, b.y - a.y) * $$anonymous$$athf.Rad2Deg;
}
Answer by DarkMatter · Sep 14, 2012 at 04:55 AM
You can get the angle between two vectors using Vector3.Angle(v3A, v3B)
http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Angle.html
This is my solution that does not have the problem of the never negative angle and is useful to understand how to use Vector2.Angle.
private float AngleBetweenVector2(Vector2 vec1, Vector2 vec2)
{
Vector2 diference = vec2 - vec1;
float sign = (vec2.y < vec1.y)? -1.0f : 1.0f;
return Vector2.Angle(Vector2.right, diference) * sign;
}
fermmmm's solution worked for me as it was important to have the positive and negative values for differentiation. Thanks for it!
How is fermmmm's script correct? It returns the angle between difference of the vectors and right vector! Assu$$anonymous$$g vec1 is Vector2.right and vec2 is Vecor2.up, the angle between them should be +90 degrees or -270 degrees(if anti-clockwise is positive rotation, as in case of 2D unity rotations about Z axis). But this function will give 135 degrees which is clearly incorrect.
The correct script is:
float AngleBetweenVector2(Vector2 vec1, Vector2 vec2)
{
Vector2 vec1Rotated90 = new Vector2(-vec1.y, vec1.x);
float sign = (Vector2.Dot(vec1Rotated90, vec2) < 0) ? -1.0f : 1.0f;
return Vector2.Angle(vec1, vec2) * sign;
}
Whatever works, is correct. You can do the same thing in different ways. I'm using it in my game AntzyP so yeah it works. The top one is for the tank barrel. The bottom one is for the tank turret.
private float AngleTo(Vector2 pos, Vector2 target)
{
Vector2 diference = Vector2.zero;
if (target.x > pos.x)
diference = target - pos;
else
diference = pos - target;
return Vector2.Angle(Vector2.right, diference);
}
private float AngleTo(Vector2 pos, Vector2 target)
{
Vector2 diference = target - pos;
float sign = (target.y < pos.y) ? -1.0f : 1.0f;
return Vector2.Angle(Vector2.right, diference) * sign;
}
fermmmm's solution is best. He should have posted that as a separate post. His works perfectly, whereas the one above does not work at all. I had the same issue.
Answer by fafase · Sep 14, 2012 at 05:55 AM
@DarkMatter's answer is the solution for fast and easy solution with no possibility of error.
Now here the mathematics solution that lies under the Angle function in case you would need to stop on the way for any reason OR you want to make it hard on you:
var vec1=Vector3(2,3,4);
var vec2= Vector3(1,-2,3);
//Get the dot product
var dot:float = Vector3.Dot(vec1,vec2);
// Divide the dot by the product of the magnitudes of the vectors
dot = dot/(vec1.magnitude*vec2.magnitude);
//Get the arc cosin of the angle, you now have your angle in radians
var acos = Mathf.Acos(dot);
//Multiply by 180/Mathf.PI to convert to degrees
var angle = acos*180/Mathf.PI;
//Congrats, you made it really hard on yourself.
print(angle);
looks like is that result is exactly the same as in Vector3.Angle and it doesn't show negative values
Yes, the result is exactly the same - that's similar to what Unity does internally to implement Vector3.Angle:
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;
}
Since the cosine is symmetrical about 0, the angle is the same no matter if "to the left" or "to the right". If you want to know the side, the cross product may help you. Supposing that both vectors are roughly in the horizontal plane (XZ), the Y component of their cross product may define the sign - for instance:
function SignedAngle(a: Vector3, b: Vector3){
var angle = Vector3.Angle(a, b); // calculate angle
// assume the sign of the cross product's Y component:
return angle * $$anonymous$$athf.Sign(Vector3.Cross(a, b).y);
}
You never get negative value because it is based on the cosine of the angle and looking at your trig circle, you will notice there is no -cos, it actually goes cos, sin, cos, -sin because cos = -cos. Rings a bell from high school? :)
So yep, going with the Cross product, you can see if the result vector goes up (pos) or down(neg) (conventional way to say as it does not necessarily goes up OR down, just one direction or the opposite). Then checking the direction tells you if the angle is pos or neg.
Answer by elliselkins · Apr 21, 2016 at 08:31 PM
Ran into trouble with the Vector3.Angle function, it was returning incorrect values. Found out there is a problem with this function when the vectors are too small, as seen in this question and answer. So I wrote my own angle functions that use Mathf.Atan2:
//This returns the angle in radians
public static float AngleInRad(Vector3 vec1, Vector3 vec2) {
return Mathf.Atan2(vec2.y - vec1.y, vec2.x - vec1.x);
}
//This returns the angle in degrees
public static float AngleInDeg(Vector3 vec1, Vector3 vec2) {
return AngleInRad(vec1, vec2) * 180 / Mathf.PI;
}
See Atan2 for more details.
This is the best solution that I have found, very convenient. Thanks!
bullet.transform.rotation = Quaternion.Euler(0, 0, AngleInDeg(bullet.transform.position, target.transform.position));
Hello, I tried to use the code of @elliselkins, and I tested it with some vectors values, but is returning an incorrect value in this case: float test2 = CalculateAngleBetweenVectors (new Vector3 (1f, 0, 0), Vector3.up); return 135 ins$$anonymous$$d of 90 and float test3 = CalculateAngleBetweenVectors (new Vector3 (-1f, 0, 0), Vector3.up); return 45 ins$$anonymous$$d of -90. Any idea? Thanks
Threw me for a loop for a $$anonymous$$ute too :).
This is because these functions measure the angle between the points, not the angle of 0,0 to these points. So take your first example, the first point is at 1,0, and the second point is at 0,1. Draw a line from the first point to the second. What angle did you have to draw that line? 135 degrees. If you drew 90 degrees then you'd be drawing straight up from the first point, but that's not where the second point is. If you want an answer of 90 degrees then this would do it: first point at 0,0, second point at 0,1.
$$anonymous$$ake sense?
Answer by Skibur · Aug 24, 2013 at 06:20 AM
Since you are using two dimensional grid axis, I use Vector2. using Vector3 is nothing different than the one I wrote;
void Update(){
Vector2 PointA = new Vector2(z, y);
Vector2 PointB = new Vector2(z, y);
float Angle = Vector2.Angle(PointA, PointB); //If the angle isn't correctly at 0, you can subtract this value by the offset degree
Debug.Log("Angle of PointA to PointB is " + Angle);
}
This is done via C#.
Follow this Question
Related Questions
How to calculate vector perpendicular to a direction vector? 2 Answers
Predicting the hit point on X axis, based on vector direction 1 Answer
Find a point in space using Vector3 angles and Raycast 1 Answer
How can I launch a GameObject at a target if I am given everything except for its launch angle? 1 Answer
Need to place an object at a certain angle form the camera and at a certaine distance 0 Answers