This is the first part of the multi-part series on Simple timer in Unity. You can find part 2 here.

When we say timer, we generally think of a time which increases from 0 to a certain time. It can be a countdown or a continuous timer that increases. It doesn't matter what the case is, but you get the meaning when anyone says timer.

A timer's usage is essential in most cases where you need to wait for a certain time. In most of the games, you might need to wait for multiple cases and for each case, you will need to create a different timer. Handling the timer may be easier if the project is small, but it will become harder as the project grows. It also makes code longer than necessary.

Ways to Run Timer in Unity

In Unity, you can run the timer using the following ways:

  1. Invoke
  2. Coroutine
  3. Update
  4. Async Await plugin

In this article, we'll be using timers with Invoke() and Coroutine

1. Timer with Invoke(): Simple Timer

Invoke() is a method provided by MonoBehaviour in Unity. It helps you run a method after a certain time interval. The method must not have any parameter and must be invoked with a time greater than 0. Using a 0-time interval is the same as not waiting. So, just calling the method is faster instead of using Invoke().

The syntax of Invoke() is:

 Invoke("TestMethod",1f);
 Invoke(nameof(TestMethod),1f);

You can use any one of the ways to use Invoke() as given above.

By calling the invoke in loop format, you will be able to run the method continuously, until you manually cancel it by using CancelInvoke(nameof(NameOfMethod)).

Creating a Timer Method Using Invoke()

Step 1: First, create a number variable which increases each second.

 private int _timer;
Timer Representing Integer

Step 2: Create a method to increase the _timer in 1-second intervals.

 private void StartTimer()
 {    
   _timer++;
   Debug.Log("Timer is : " + _timer);    
   Invoke(nameof(StartTimer), 1);
 }
Method to Increase the Timer

After calling the StartTimer(), your timer will increase from 0 until you cancelInvoke() to stop the loop of the timer invoked.

You can create a new method with the following code to stop this timer.

CancelInvoke(nameof(StartTimer));
Timer Representing Integer

This is just a normal timer which starts from 0 and increases until you cancel it. We can provide a time-out value so that timer increases up to the given specific time and stops by itself but let's not do that with Invoke. It is not good to use Invoke for this type of work. It can be done easily using Coroutine , and we will do so later in the article.

The full code of this is given below.

public class TimerWithInvoke : MonoBehaviour
{
    private int _timer;

    private void Start()
    {
        StartTimer();
    }

    private void StartTimer()
    {
        _timer++;
        Debug.Log("Timer is : " + _timer);
        Invoke(nameof(StartTimer), 1);
    }

    private void StopTimer()
    {
        CancelInvoke(nameof(StartTimer));
    } 
}
Full Code for TimerWithInvoke

2. Timer with Coroutine

Coroutine is one of the functions provided by Monobehaviour to use when we need to apply the waiting process in the game. As the coroutine runs in separate thread from the normal running code in Unity, we can run it without any problem to keep the record of the timer we need without affecting the running code. You can also wait until the timeout is called and continue your code.

The timer using coroutine is also very easy. We just need to run a loop which increases the timer value until we stop it or give a time-out value. When using coroutine method, don't forget to add IEnumerator as the return value for the method. Make sure that the starting of coroutine is done in the following way.

 private IEnumerator _timerCoroutine;
 private int _timer;
 private void StartTimer(int totalTime)
        {
            //reset the timer at the start
            _timer = 0;
            _timerCoroutine = StartTimer(totalTime);
            StartCoroutine(_timerCoroutine);

        }
Starting the Coroutine Method

Here, _timerCoroutine is a global IEnumerator holding the IEnumerator of the StartTimer() method.  

The reason for using separate IEnumerator to hold the running IEnumerator of the coroutine is because stopping this coroutine is effective if we apply StopCoroutine to the running IEnumerator rather than the method directly.

The stopping method for this coroutine looks like this.

    public void StopTimer()
    {
        if (_timerCoroutine != null)
        {
            StopCoroutine(_timerCoroutine);
            _timerCoroutine = null;
        }
    }
Stopping the Coroutine method

Now improvise the StartTimer() we mentioned above in Invoke() section for coroutine use, as shown below.

 private IEnumerator StartTimer(int totalTime)
    {
    	while (_timer < totalTime)
        {
            //waiting 1 second in real time and increasing the timer value
            yield return new WaitForSecondsRealtime(1);
            _timer++;
            Debug.Log("Timer is : " + _timer);
        }
 //TODO: call for the method or call a callback action to inform that the timer is up.
 }
        
       
Timer with Coroutine

Give a total time you want the timer to run in the parameter and run a loop until the given time and a simple timer is completed with coroutine.

Adding Callback When Timer is Up

You can add an Action to be triggered when the timer is up. It helps the developer continue the work that has to be run when the timer is up. So let's just add a little change to the existing code and create a timer with callback in the above code.

First, save the action provided at the start of the timer to the OnTimeOut action.

.......
 public Action OnTimeOut;

 private void StartTimer(int totalTime, Action timeOut)
        {
            OnTimeOut = timeOut;
            //reset the timer at the start
            _timer = 0;
            _timerCoroutine = StartTimer(totalTime);
            StartCoroutine(_timerCoroutine);
        }
Addition of Action Callback OnTimeOut

Then just trigger the action when the timer is up.

You can directly add the callback action in the parameter and trigger it when the timer is up. You can also create a global action that will hold the provided action in the parameter and be triggered when the timer is up.

The process is up to you, but for now, we will use a global action to hold the action to be triggered on time up, as mentioned in the above code.

    private IEnumerator StartTimer(int totalTime)
    {
        while (_timer < totalTime)
        {
            //waiting 1 second in real time and increasing the timer value
            yield return new WaitForSecondsRealtime(1);
            _timer++;
            Debug.Log("Timer is : " + _timer);
        }

        //trigger the timeout action to inform that the time is up.
        OnTimeOut?.Invoke();
    }
   
Timeout Action Trigger Added

Lastly, when stopping the timerCoroutine, remove the assigned action to our global action OnTimeOut.

    public void StopTimer()
    {
        if (_timerCoroutine != null)
        {
            StopCoroutine(_timerCoroutine);
            _timerCoroutine = null;
            OnTimeOut = null;
        }
    }
Stopping the Coroutine method
💡
OnTimeOut action is set to null when stopping the timer to avoid the triggering of the assigned action multiple times after it has been stopped. So, don't forget to remove it.

Here is the full code for TimerwithCoroutine.

```
public class TimerWithCoroutine : MonoBehaviour
{
    private int _timer;

    /// <summary>
    /// Ienumerator which will holds the Ienumerator method that is used to run the timer.
    /// </summary>
    private IEnumerator _timerCoroutine;

    /// <summary>
    /// Triggered when timer is completed and timeout is to be called.
    /// </summary>
    public Action OnTimeOut;

    private void Start()
    {
        StartTimer(10, TimeOut);
    }

    private void TimeOut()
    {
        Debug.Log("Your timer is up.");
    }

    public void StartTimer(int timer, Action onTimeOut)
    {
        OnTimeOut = onTimeOut;
        //Reset the timer to 0 before starting the timer
        _timer = 0;
        _timerCoroutine = StartTimer(timer);
        StartCoroutine(_timerCoroutine);
    }

    private IEnumerator StartTimer(int totalTime)
    {
        while (_timer < totalTime)
        {
            //waiting 1 second in real time and increasing the timer value
            yield return new WaitForSecondsRealtime(1);
            _timer++;
            Debug.Log("Timer is : " + _timer);
        }

        //trigger the timeout action to inform that the time is up.
        OnTimeOut?.Invoke();
    }

    public void StopTimer()
    {
        if (_timerCoroutine != null)
        {
            StopCoroutine(_timerCoroutine);
            _timerCoroutine = null;
            OnTimeOut = null;
        }
    }
}
Full Code for TimerWithCoroutine

To Summarise,

we have just finished creating a simple timer in two ways; Invoke and Coroutine in this article. The other two ways, update and async await plugin will be described in the second part of this article.

Hope you found this article helpful. Subscribe to stay tuned for part 2.