Float precision

Float precision issues is something you always know is out there, but something you rarely need to pay any thought to. As you can guess, it’s an issue we ran into. When making a build, one of our puzzles involving a rotating platform would seemingly work, but not fire the event it was suppose to at the end of it’s movement. Not firing this event essentially locked the entire puzzle as the player was not able to rotate the platform into any of the states required to proceed.

After a lot of debugging and generally tearing our hair out, me and Kenth finally found the cause of the issue. To keep track of what rotation (and if it had reached its destination) the delta rotation was calculated and then added to a variable each frame, simply:

actualRotationDelta = Mathf.SmoothDampAngle(...) - m_rotatedDegrees;
... do rotation ...
m_rotatedDegrees += actualRotationDelta;

It turns out, in this particular case, the value calculated by Unitys SmoothDampAngle got below the Epsilon value at high framerates. What this means in practice is that the value got so small enough for it to more or less equal zero, making it completely useless.

The way we resolved this issue is to simply check if whether value of actualRotationDelta is less than the Epsilon and if we’re close to the rotation we’re rotating to. This is not a optimal solution but considering the time constraints we had it was the simplest to implement.

actualRotationDelta = Mathf.SmoothDampAngle(...) - m_rotatedDegrees;

if (actualRotationDelta < Mathf.Epsilon && Mathf.Abs(m_rotatedDegrees – targetRotation) < 0.001f)
{
… snap to target rotation …
}
else
{
… do rotation…
}

Lesson learned here is to prefer lerp, slerp and smoothstep functionality in the future. Sure, it’s slightly more hassle but you’ll completely steer clear of these sort of issues.

Posted in Game Development, Programming, School and tagged as