Most Accurate Timer in Unity

In our current project, a large part of the functionality relies on a timer. When it boils down to it, the accuracy of the timer isn’t hugely important so long as it’s consistent, but I figured the most accurate method is likely to also be the most consistent.

There are three basic ways to implement a timer in Unity:

  1. +=deltaTime in Update()
  2. InvokeRepeating
  3. Coroutine

I’ve seen quite a bit of discussion about these different methods, but there appears to be some disagreement about what’s best and why. None of the discussions I’ve found have included the results of any tests to compare them or demonstrate accuracy or efficiency.

I’ve been avoiding Update() where practical – using Coroutines or Invoke instead if something doesn’t need to be checked or done for every frame of an object’s life. But with two other methods available, I didn’t know whether a Coroutine with WaitForSeconds or an Invoke is a better way to create a simple delay. It doesn’t really matter too much for one off events, but for repeating events, or if you have lots of them, delays can add up fairly quickly.

Here is the basic code I used to test each method:

  1. The Update() method adds deltaTime (the time it took to complete the last frame) to its counter, every frame.
  2. The Invoke method is called from Start(), and adds the increment to its counter each time it’s called – once per increment.
  3. The coroutine is started from Start(), and then uses WaitForSeconds to pause for the increment time before adding the increment to its counter, and then repeating.

One difference to most Coroutine examples is that this one creates a WaitForSeconds instance before starting the Coroutine timer. Most examples create a new WaitForSeconds every increment, but it’s better to create something once and reuse it than to create and throw away over and over. There’s enough garbage being created with all those strings without adding more.

The Results

So what is the most accurate timer in Unity?

Well, it’s immediately obvious that the Coroutine isn’t remotely accurate. At one second increments, it only takes a few seconds for it to be noticeably lagging, losing 8-10 milliseconds per update, or around 1/2 a second per minute. More frequent increments cause it to lose time more quickly, as you’d expect.

The Update method behaves differently for Unity 5.3.5 and 5.4, but is much more accurate than the Coroutine. In 5.3.5, the Update version falls behind gradually, losing 1 second after around 70 minutes. In 5.4 the Update version keeps up for about an hour, but after that it can either gain or lose time, ending up a second or more behind or ahead of the actual time.

The Invoke method stays synced with the time for over an hour, and after longer periods has consistently been closer to the correct time than the Update method.

Faster increments effect the results. An increment of 1/10 of a second (or 100 milliseconds) causes the Coroutine to fall behind more quickly, and the Invoke becomes slightly less accurate, but still often more accurate than Update.

Another thing to be aware of is that losing and regaining focus really messes with the timers. I was getting wildly varied results until I realized that each time Unity lost focus, the timers would go out of whack – most obviously the Update method.

Verdict

For slower increments, anything over 100 milliseconds, Invoke definitely comes out the winner. It’s consistently as or more accurate than the Update method without needing to do calculations every frame.

For faster increments, under 100 milliseconds, Invoke becomes slightly less accurate, but we also start to lose the benefit of invoking over calculating every frame anyway. The closer the increment gets to the frame rate, the more benefit there is to using the Update method, but given how slight the difference is, I would still likely choose Invoke for anything slower than the average frame rate.

Coroutines definitely have their uses, but the overhead is too great for a timer like this unless it’s combined with other functionality that needs to occur over multiple frames.

Now I just need to test in my app with everything else going on to see if that makes a difference…

Most Accurate Timer in Unity

Leave a Reply

Your email address will not be published. Required fields are marked *