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:
- Invoke
- Coroutine
- Update
- 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;
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);
}
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));
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));
}
}
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);
}
Coroutine
MethodHere, _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;
}
}
Coroutine
methodNow 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.
}
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);
}
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 AddedLastly, 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;
}
}
Coroutine
methodOnTimeOut
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;
}
}
}
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.