0

If tried searching the internet but I couldn't find the anwser.

I'm trying to calculate the angle between 2 vectors, seen from the first vector.

So if vector 1 is at 0,0 and vector 2 is at 1,1 the heading would be 45.

at 1,0 it would be 90.

at -1,0 it would be 270.

Is there a simple solution to create this?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Mark
  • 132
  • 3
  • 13
  • say Mark, don't use "heading" as terms like heading, bearing, have technical meanings in game physics. Best just to refer to the "angle" or I think specifically you want the "overhead clockwise angle" – Fattie Aug 06 '16 at 13:19
  • just one point, also check out the dot product (there's a function built-in in Unity) which is often relevant to what you're doing. – Fattie Aug 06 '16 at 13:19
  • This is a valid question; I would love to know who felt the need to downvote it and why. – Max Yankov Aug 07 '16 at 08:44
  • right @MaxYankov - someone "downvote bombed" the question, heh. – Fattie Nov 21 '16 at 12:05

5 Answers5

1

I can't test it atm but this should work:

double getHeading(Vector2 a, Vector2 b)
{
    double x = b.x - a.x;
    double y = b.y - a.y;
    return Math.Atan2(y, x) * (180 / Math.PI);
}
91378246
  • 488
  • 6
  • 14
1

Given a offset vector (relative to 0,0,0 for instance)

float resultInDegrees = (360 + Mathf.Atan2(rotateVector.x, rotateVector.z) * (180 / Mathf.PI)) % 360;

Note that we're adding 360 and taking the modulus of the result, otherwise you'll get from 0 - 180, then negative angles.. This converts -1 degrees to 359 degrees, as the original poster had requested.

Rusty Parks
  • 173
  • 1
  • 8
  • 1
    I would like to clarify that C#'s use of the `%` operator is for the "remainder" operation. `-1 % 360` does **not** result in `359`, it results in `-1` because `-1 / 360 = 0 r -1`. In short, while it is correct to say that `(360 + angle) % 360` will end up with a value in [0, 360) in this scenario, it is not correct to say that `%` is the "modulus of the result". – absoluteAquarian Feb 12 '21 at 00:24
0

This is not Unity, this is a math question.

You need to use vector dot multiplication. It's built into unity and equals the product of the lengths of the vectors multiplied by the cosine of the angle between them, so you easily get the angle between the vectors out of it. Of course, unity has a built-in function for that.

Since a lot of operations involving vectors are performed every frame, it helps to be aware of perfomance implications of the code you're running. Sadly, other solutions to this questions are more computationally complex. Also, keep in mind that often you don't need the angle itself: the cosine of the angle is actually easy to work with.

Of course, this answer doesn't cover the case of 270 degrees. However, for this kind of applications, Quaternions fit much better. Basically, the 270 case requires you to know the up vector to calculate it, and vectors themselves (as math abstractions) don't contain that information — so, on the math level, you wouldn't have any way of telling apart the vectors that have 270 and 90 degrees between them.

So, if you really need the 270 case, create quaternions from the vectors (by the way, you can see that up vector is a distinct piece of information here) and then calculate the angle between them. Unlike vectors, Quaternions were created to deal with rotations and directions and Unity has all the functions implemented for that.

Max Yankov
  • 12,551
  • 12
  • 67
  • 135
  • Thank you for your anwser Max, this was indeed a math question. But I was hoping there would be a simple unity function which would calculate this for me. I decided to do it manually. – Mark Aug 07 '16 at 11:35
  • Well, if you use quaternions, there is. If you use vectors — you won't get the 270 degrees case. – Max Yankov Aug 07 '16 at 12:12
-2

All thanks for your response, I decided to go for a manual calculation. For anyone who finds this question after me, this is how I did it:

double calculateHeading(Transform target){
    double newHeading = 0;

    Vector3 vectorToTarget = target.position - transform.position;
    double x = vectorToTarget.x;
    double y = vectorToTarget.y;

    if (x == 0 && y > 0) {
        newHeading = 0;
    } else if (x == 0 && y < 0) {
        newHeading = 180;
    } else if (x > 0 && y == 0) {
        newHeading = 90;
    } else if (x < 0 && y == 0) {
        newHeading = 270;
    } else if (y < 0) {
        newHeading = 180 + (Mathf.Rad2Deg * Mathf.Atan (vectorToTarget.x / vectorToTarget.y));
    } else if (y > 0) {
        newHeading = 360 + (Mathf.Rad2Deg * Mathf.Atan (vectorToTarget.x / vectorToTarget.y));
    }

    if (newHeading > 360) {
        newHeading -= 360;
    } else if (newHeading < 0) {
        newHeading += 360;
    }

    return newHeading;
}
Mark
  • 132
  • 3
  • 13
  • This can be done in 2 lines of code but instead you went with 21... Check out this video: https://www.youtube.com/watch?v=LNLVOjbrQj4 – FanManPro Sep 01 '19 at 20:35
-2

Dude, did you tried to use google? I just googled "unity angle between two vectors" and found official documentation.

https://docs.unity3d.com/ScriptReference/Vector3.Angle.html

var angle = Vector3.Angle(Vector3 from, Vector3 to); 

or in your case

var angle = Vector2.Angle(Vector2 from, Vector2 to); 
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
  • "The angle returned is the unsigned angle between the two vectors. This means the smaller of the two possible angles between the two vectors is used. The result is never greater than 180 degrees." – Rusty Parks Nov 20 '20 at 19:50