0
\$\begingroup\$

I have my own 2d game and I am attempting to calculate the angle between 2 GameObjects.

My Problem: My function that is meant to calculate the angle(direction) between 2 Vector3's doesn't appear to be correctly calculating the angle. It always returns a value thats between 89.1 and 89.9, its never any other value.

What am I doing wrong? Can you help me to get my function to correctly calculate the angle between 2 Vector3's?

float getAngle(Vector3 p1, Vector3 p2) {

    // If p1 or p2 == Vector3.zero then this funciton wont work. What shd I do in this case?

    float coefI  = p1.x * p2.x;
    float coefJ  = p1.y * p2.y;
    float coefK  = p1.z * p2.z;
    float scalar = coefI + coefJ + coefK; 
    float magnitude1 = p1.sqrMagnitude;
    float magnitude2 = p2.sqrMagnitude; 

    Debug.Log (System.String.Format ("{0}, {1}, {2}, {3}, {4}, {5}", coefI, coefJ, coefK, scalar, magnitude1, magnitude2));
    return (Mathf.Acos ( scalar / (magnitude1 * magnitude2) ) * Mathf.Rad2Deg); // Always returns between 89.1 and 89.9 for some reason
}

void Update() {
    Debug.Log( getAngle (Input.mousePosition, transform.position) );
}
\$\endgroup\$
6
  • \$\begingroup\$ Log the value of the normalized dot product: scalar / (magnitude1 * magnitude2). If one of the vectors is zero, simply return 0. It does make some sense for a simulation: the zero vector is aligned with any other 3D vector so.. in a way, their angle is zero. \$\endgroup\$
    – teodron
    Aug 17, 2012 at 8:53
  • \$\begingroup\$ @teodron so your saying to calculate the angle I shd log it and not use Acos? \$\endgroup\$
    – Mack
    Aug 17, 2012 at 8:55
  • \$\begingroup\$ No, try and see if you get some sensibly different dot product values that you feed to the acos function. If that's the case, i.e. they're pretty close as well, the vectors are indeed almost perpendicular and you should look somewhere where the function is called.. \$\endgroup\$
    – teodron
    Aug 17, 2012 at 8:59
  • 1
    \$\begingroup\$ If you insist on writing your own dot product calculation, at least order the operations so that they can more easily be optimised to use fused multiply-add: p1.x * p2.x + (p1.y * p2.y + (p1.z * p2.z)) \$\endgroup\$ Aug 17, 2012 at 9:31
  • 1
    \$\begingroup\$ @teodron: Unity has several scripting languages; the one here is C#, based on MonoDevelop. C#'s runtime will have support for FMA when the consumer-grade CPUs support it better (first ones will be here in this year from AMD and next year from Intel; consumer-grade GPUs support it for a while now, which is important if you use GPGPU), but as usual the optimisation will not kick in for all but the most obvious cases until some time after that, so it's better to help the VM along. It's not like the "optimised" version is any harder to read ... \$\endgroup\$ Aug 17, 2012 at 9:52

1 Answer 1

3
\$\begingroup\$

sqrMagnitude is the vector length squared, but you need the vector lengths. Simple fix:

return (Mathf.Acos ( scalar / Mathf.Sqrt (magnitude1 * magnitude2) ) * Mathf.Rad2Deg);

Of course you could just use Unity's angle calculation function: http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Angle.html

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .