Shaders are also affected by this, and it’s particularly problematic because you cannot simply switch to a double value. If you want to animate shaders over time and your app will run for days, you should consider using a fixed loop where the modulo function resets the value to 0 once the loop ends.
Consider Using Time.timeAsDouble
Use Time.timeAsDouble
instead of Time.time
if you want to prevent time-related bugs after extended runtime of the app. We once had an app running on a machine that was supposed to restart every day. However, for some reason, it didn’t restart for three days. The result was that some lights of the installation were flashing erratically. The location was 400km away from us.
What Happened?
Fortunately, we add remote logging to our apps whenever possible and quickly discovered that the machines hadn’t restarted as scheduled. Back then this was neither our responsibility nor was it expected to be an issue. Yet we immediately suspected the issue was timing-related. To test this, we simulated a high Time.time
value by adding one day in seconds, which is 24 * 60 * 60 = 86,400. The animation already began to degrade, and it worsened as we increased the value.
In the affected method, we use trigonometric functions to animate pixels on a texture, which controls the studio lights (by displaying the texture on a second screen). As you may know, floating-point numbers have a limited precision of about 7 digits. For most use cases, this is sufficient—but only if the integer part stays within 2 or 3 digits. However, once the integer part grows to 5 digits, decimal precision drops significantly. In our case, this caused noticeable errors because we applied additional offsets and scaling to that number.
How did we fix it? We simply switched to a double-precision value, providing twice the accuracy, by using Time.timeAsDouble
.
How Long Does This Hold Up?
Using a float for timing, your app might only run reliably for one or two days before visual artifacts appear. By switching to doubles, your app can run for a year or longer without any issues. Yet, who's games run for that long anyways?
Avoid Using Time Variables When Possible
Of course, there are situations where floats work well. However, in our case, we were looking for a quick and flexible solution. One idea would be to reset the time at fixed intervals, but this should happen without any noticeable jumps.
Typically, we implement animations by incrementing or decrementing variables and resetting them at the end.
float timerDuration = 3f;
float timer;
void Update()
{
timer -= Time.deltaTime;
if (timer <= 0f)
{
timer += timerDuration; // Reset by adding the value to catch overshoot (timer will be lower than 0)
}
//Animate here
}