#7 Making the Countdown Timer in C# – Labyrinth Series

Introduction

In this article we are going to see how to program a timer in C#, the operation will be counting backwards from the initial values of minutes and seconds that we indicate and in addition the Timer will be in charge of updating the information in the user interface created in the video 5 of the series of the labyrinth. Here is the article in which we created the user interface, in short we created some elements for the Canvas, which will allow the user to start playing and see information about the game.

Go to the project’s Main Page

Before we begin, I invite you to watch the video of this article.

Objective

The prototype is a first-person game in which the stage is a maze. Inside the maze, there will be a hidden object that must be found before time runs out.

Now we’re about to solve the part where time runs out. In this article we’ll create a script that is going to work as a countdown timer.

The Timer will start the countdown from a value of minutes and seconds that we will indicate in the inspector, this means that every second of clock we must update the information.

The Script Timer will also modify the value of the Canvas text element (top of figure 1).

When the time count reaches zero, the Script Timer will execute the EndGame method of the GameControl Script, this way the game will end and we will return to the main menu.

escena en unity, en la parte superior un objeto texto que mostrara el valor del timer en c#
Fig. 1: The aim is to control the text at the top so that it shows the remaining time.

Step by Step

We start by creating the Timer Script and open it in the editor. In order to access to the UI components, like on-screen texts and buttons, we need to include the UnityEngine.UI namespace at the top of the script (figure 3).

nuevo script c# llamado timer en unity
Fig. 2: A new C# Script named Timer is created.

paquetes importados en el script timer
Fig. 3: Make sure you import UnityEngine.UI to access the user interface methods.

Fields

To make the countdown timer work we’ll need a couple variables.

In figure 4 you can see a “[SerializeField]” instruction above certain variables, this simply makes the variables and fields to appear in the inspector.

The two serialized integers (minutes and seconds) are the initial values of the countdown timer.

While the two private integers (m and s) will be used to keep track of time.

campos definidos en script timer
Fig. 4: Fields to program the countdown timer’s functionality.

We also need a Text type object to have the reference of the Text component of the Canvas.

Select the “Control” object from the hierarchy and assign the Timer Script. We see in the inspector the serialized fields of the Script Timer: minutes, seconds and timerText.

unity ventana inspector mostrando componentes de gameobjects
Fig. 5: Assign the Script Timer to the GameObject Control hierarchy.

jerarquia de un proyecto en unity
Fig. 6: Take the GameObject Timer and take it to the TimerText field in the previous figure.

Let’s write one minute and five seconds for the initial values of the countdown timer. Then take the Timer GameObject from the hierarchy (the one that contains the Text component, figure 6) and drag it to the timerText field.

unity ventana inspector mostrando componentes de gameobjects
Fig. 7: We write values to initialize the variables.

In figure 7 we can see that in the timerText field a Text type component has been recognized.

Methods to implement

Having in mind how a Countdown timer works, some ideas of possible methods emerge. First for the Timer to start working we’ll create a method called StartTimer(). Then another method that runs at intervals of a second that is going to take care of incrementing the time value, we’ll call it UpdateTimer(). A third method to stop the Timer, that will be executed when it finishes counting, this will be StopTimer().

script c# para resolver el funcionamiento de la cuenta regresiva
Fig. 8: We remove the Update method and create new methods to solve the problem.

Finally, a method that modifies what is being shown in the user interface, this method will be called WriteTimer() and will take as parameters two integers for the minutes and seconds.

metodo en c# para escribir un timer
Fig. 9: We also added a method to write the Timer.

Note that the parameters required by this method have exactly the same name as the two integers previously defined, which are in charge of keeping track of the time.

This is done so on purpose to talk a little about contexts in programming, probably for later in another article.

Programming the functions of the countdown timer

UpdateTimer() Method

We have proposed some methods intuitively considering roughly the functioning of the Timer, now we must fill those methods with C# instructions that are the ones that will do the job.

The UpdateTimer method will take care of subtracting a second, checking if the time has not run out, and modifying the minutes accordingly. Finally, it will use the WriteTimer method, passing you the values of minutes and seconds. Figure 10 shows an example of how to implement this.

seria de instrucciones en c# para refrescar el valor de un timer
Fig. 10: Instructions for the UpdateTimer method.

In the first instruction of the method we decrease by one unit the variable seconds, then we check if this variable is negative, i.e. if previously it was worth 0 and now it is worth -1.

If this happens we notice if the minutes variable is worth 0, if it is true this means that the time of the Timer is exhausted (I leave the comment //endGame in that region). If the minutes are not equal to zero, we decrease the minutes variable by one unit and make the seconds variable worth 59.

Finally we execute the WriteTimer method passing the variables m and s as parameters.

WriteTimer() Method

This method will take care of modifying the Text object that we had defined. Depending on whether the variable has a single digit (i.e. less than 10) or has two digits (greater than or equal to 10), we are going to execute the instructions seen in figure 11.

What is done is to concatenate a series of strings or text strings, in the case that s is less than 10, we concatenate a 0 in front of the seconds so that it conserves the format of two numbers.

There are other ways to do this such as setting a format for text strings, but in this way we take the opportunity to see how easily we can concatenate text using the sum operator.

seria de instrucciones en c# para refrescar el valor de un timer
Fig. 11: Instructions for the WriteTimer method.

StartTimer() Method

This method will perform the initialization of the Timer, that is, we take the minutes and seconds variables that appeared in the inspector with the initial values and assign them to the variables m and s that carry the count.

The method to write the values in the graphical interface is executed.

Finally we use the Invoke method, giving as parameters the string “updateTimer”, which is the name of the method and the second parameter is 1f that represents a second. This will make the updateTimer method run after one second.

seria de instrucciones en c# para iniciar un timer
Fig. 12: Instructions for the StartTimer method. Invocation of updateTimer.

We are going to add this same instruction at the end of the updateTimer method, this way the method will invoke itself every second. This can also be done using the InvokeRepeating method instead of Invoke.

seria de instrucciones en c# para refrescar el valor de un timer
Fig. 13: The updateTimer method invokes itself every second.

Interactions between Scripts

The Timer is like a device that fulfills its function, we can configure it, put it to run and stop it. With this in mind, we are going to make the GameControl Script the one that controls the Timer, being able to start and stop it using its public methods.

If you wanna read more about executing functions from other Scripts you can check this article.

First we are going to define a Timer type object to use in the GameControl Script.

Then in the Start method we find the Timer reference that is assigned to the same GameObject Control hierarchy (hierarchy in figure 6).

script para controlar el juego
Fig. 14: Add a Timer type object to the fields of the GameControl Script. Reference is found in the Start method.

In figure 14 we see underlined, the statement of this object Timer and how we find the reference in the Start method.

Now the GameControl Script has the reference of the Script Timer instance, this means that you will be able to access its methods and public fields using the dot operator.

In GameControl’s StartGame method we’re going to make the Timer start working.

metodo start game del script que controla el juego
Fig. 15: In the startGame method we execute the Timer startTimer method.

At the same time, we also want the Timer to have some way of telling the GameControl Script that time is up, so we also need the reference to the GameControl object within the Timer Script.

In figure 16 we see the declaration of this object and how the reference is found within the Start method.

fragmento del timer en c#
Fig. 16: Add a GameControl type object in Timer and find the reference in Start.

For now we are going to make that when the time runs out the game ends and we return to the main menu, that is to say the same thing that would happen if we press the Escape key. This can be done by running GameControl’s EndGame method.

In previous videos we had declared it with private visibility, which implies this method can not be executed from an external context, for example the Script Timer.

So that we can execute it from the Timer Script we change to public visibility. See figures 17 and 18.

visibilidad privada de un metodo, no accesible desde otro contexto
Fig. 17: We observe that the visibility of the EndGame method is private, that’s why we can’t execute it from Timer.

visibilidad publica de un metodo, accesible desde otro contexto
Fig. 18: We change the visibility to public so that it is accessible from another context.

Now if, in the UpdateTimer region where we detected that the account reaches zero (we had left the //endGame comment), we execute the EndGame method of the GameControl Script and then the return sentence to finish the execution of the UpdateTimer method.

programacion de un timer en c# utilizando invoke
Fig. 19: We identify the region of the code in which time has run out and execute the EndGame method.

In the EndGame method of the GameControl Script we are going to stop the Timer, as can be seen in figure 20.

Why didn’t we make the UpdateTimer method stop the Timer when the count reaches zero?

It could have been done in many different ways, at the time I chose to do so bearing in mind that the Timer only serves the function of keeping track of time and warn when the time runs out, then the GameControl Script that uses the Timer decides what to do with it.

metodo c# unity que se encarga de detener el juego
Fig. 20: In the EndGame method we execute the action to stop the Timer.

StopTimer() Method

In this method we will only cancel all invocations that may be pending, we could also reset the timer values to the initial values.

As an observation, in the code of figure 19, if the Timer reaches zero, the EndGame() method is executed and then the instruction return, which means that the program is forced to exit the current method, therefore updateTimer() will not be invoked again and the CancelInvoke() instruction would not be necessary.

But we could execute the EndGame method due to other reasons, for example pressing the Escape key or the player wins the game, in those cases it is necessary to cancel the UpdateTimer invocations.

metodo para detener un timer en c#
Fig. 21: In the StopTimer method we cancel invocations that may be pending.

Final tests

I’m going to make sure it works as expected, first I’m going to set 0 minutes 5 seconds as initial values and enter the game mode.

unity ventana inspector mostrando componentes de gameobjects
Fig. 22: I set the initial values to quickly observe the results.

When entering the game mode the Timer starts with 5 seconds, makes the countdown and when it reaches 0 we see in figure 24 that returns to the main menu.

escena en unity que funciona como menu principal, boton para empezar el juego
Fig. 23: We entered the game mode to test the operation of the countdown.

escena en unity, en la parte superior un objeto texto que muestra el valor del timer en c#
Fig. 24: When the time runs out, the result is the same as pressing the Escape key, the EndGame method is executed and we return to the main menu.

Now we verify that the format of two numbers for seconds is respected and that the minutes are correctly decremented when the seconds go from zero to 59. We start the Timer with 10 minutes 5 seconds and enter the game mode.

We observe that the format of two digits is respected for the seconds and in addition the minutes are decremented correctly. The exercise is finished.

escena en unity, en la parte superior un objeto texto que muestra el valor del timer en c#
Fig. 25: Test again with the timer in 10 minutes 5 seconds.
escena en unity, en la parte superior un objeto texto que muestra el valor del timer en c#
Fig. 26: The format of the countdown is respected.

Conclusion

We have managed to complete our Timer in C#, which serves the function of keeping track of time, displaying it in the user interface and when the time runs out notify the GameControl Script to decide what to do.

This timer could have been implemented in several different ways, the Invoke method was chosen in this case, because I considered a quite simple alternative.

We saw how easily we can modify a text component of the Canvas as long as we have its reference, so we can use this for other things like scoring, information messages, etc..

We began to introduce little by little the concept of objects, how each has a specific function and have references to other objects to make use of their methods and public parameters. This is an extremely interesting and useful topic for creating object-oriented solutions.

Leave a Comment

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