0
\$\begingroup\$

I'm having trouble understanding why with this script, Vector3.Angle() sometimes will never reach 0.

This question comes from me trying to make a "turret" that rotates to face a target position. It was not quite working (the angle between the turret and target would get very close to 0 and start flipping between + and - values, and never actually 0).

So to debug it I stripped the script down, and used transform.LookAt(), trying to isolate the problem. However, even using LookAt(), the Vector3.Angle() method still -sometimes- refuses to report the angle as 0, and I'm not sure why.

                //Turret does not care about any Y position differences...
                Vector3 currCustom = currentTargetPosition;
                currCustom.y = transform.position.y; //ignore Y differences...
                Debug.Log("currCustom is: " + currCustom);

                Vector3 directionVector = currCustom - transform.position;
                Debug.Log("directionVector is: " + directionVector);

                float angle = Vector3.Angle(transform.forward, directionVector);
                Debug.Log("angle is: " + angle);

                transform.LookAt (currCustom);

The attached image should also help demonstrate what is going on (note that the object doing the checking is an empty GameObject located roughly where the orange square is).

Any ideas as to what I'm doing wrong are appreciated, thank you for reading. enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ Does normalizing the vectors make a difference? \$\endgroup\$ – Jon Mar 4 '15 at 5:10
  • \$\begingroup\$ @Jon: Good catch, normalizing "directionVector" seems to make the math work out (transform.forward is already normalized). So if you make this an answer I'll mark it as correct. If possible, could you elaborate on how normalizing the vector makes the math work out? I'm familiar with the concept of normalization, but I just don't fully understand the mathematical significance in this case. Either way, thanks again. \$\endgroup\$ – Joe Mar 4 '15 at 6:50
  • \$\begingroup\$ Given a difference of .02 degrees, I would be very inclined to assume it's a floating point precision problem. \$\endgroup\$ – rutter Mar 5 '15 at 2:15
2
\$\begingroup\$
if (Math.abs( angle) > mindelta )
      transform.LookAt (currCustom);

I think it depends on floating point math errors, I suggest to define a min angle (mindelta in my code example) inside wich, the turret doesn't move

\$\endgroup\$
  • \$\begingroup\$ This. Float point math isn't precise, and if you check something with == 0f, or expect that a * b * c will always equal a * c * b, you're going to have a lot of moments like this. You should always expect float-point to be imprecise. \$\endgroup\$ – Max Yankov Mar 4 '15 at 10:19
  • \$\begingroup\$ @ dnk drone.vs.drones & golergka: Fair enough, I'll take that approach from here on out. \$\endgroup\$ – Joe Mar 7 '15 at 12:55
0
\$\begingroup\$

Does normalizing the vectors make a difference?

@Jon: Good catch, normalizing "directionVector" seems to make the math work out (transform.forward is already normalized). So if you make this an answer I'll mark it as correct. If possible, could you elaborate on how normalizing the vector makes the math work out? I'm familiar with the concept of normalization, but I just don't fully understand the mathematical significance in this case. Either way, thanks again.

Borrowed from this question:

double Vector3AngleBetweenTwoPoints(Vector3 p1, Vector3 p2)
{
return acos(Vector3DotProduct(p1, p2) / (Vector3Magnitude(p1) * Vector3Magnitude(p2)));
}

When p1 and p2 are both unit vectors, this condenses to:

return acos(Vector3DotProduct(p1, p2));

Since p2 was not normalized, the angle coming out of acos() was being arbitrarily scaled by a factor of (1 / distanceBetweenObjects).

It's worth noting that the length of a 2X-scale world matrix's forward vector is 2.0. To find the angles between world objects, you'll definitely need to normalize.

Edit:
Although you aren't really close to it, I'd also mention a constant float value called Epsilon. It represents the smallest value that can be precisely represented by the float equation and anything that evaluates to less than that is usually considered "0 enough".

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.