#7 Timer para cuenta regresiva en Unity

Información actualizada sobre esta entrada

Este artícu­lo pertenece a una serie que con­siste en hac­er un juego sim­ple en primera per­sona acer­ca de encon­trar obje­tos den­tro de un laber­in­to. Es una de mis primeras series de cuan­do empecé el canal, aho­ra he mejo­ra­do mucho este proyec­to y puedes descar­gar el códi­go fuente para impor­tar­lo en tu pro­pio proyec­to de Uni­ty. Algún día vamos a hac­er un remake de esta serie, suscrí­bete a mi canal para estar al tan­to del nue­vo con­tenido sobre Blender, Uni­ty y pro­gra­mación.

Sígueme en itch.io y descarga el código fuente de este proyecto

PUEDES TESTEAR ESTE JUEGO AQUÍ. TAL VEZ TARDE UN POCO EN CARGAR
🔻

MOVEMENT: WASD CAMERA LOOK: MOUSE

Introducción al artículo original

En este artícu­lo vamos a ver cómo hac­er un timer en Uni­ty, el fun­cionamien­to será con­tar hacia atrás des­de los val­ores ini­ciales de min­u­tos y segun­dos que indique­mos y además el Timer se encar­gará de actu­alizar la infor­ma­ción en la inter­faz de usuario crea­da en el video 5 de la serie del laberinto.

En el artícu­lo en el que creamos la inter­faz de usuario, lo que hici­mos fue crear algunos ele­men­tos para el Can­vas, que per­mi­tirán al usuario comen­zar a jugar y ver infor­ma­ción sobre el juego. 

Ir a la página principal del proyecto

Vídeo relacionado a este artículo

Cómo hac­er un timer para cuen­ta regre­si­va en Unity


Descargar Scripts de esta parte del proyecto

My first game in Uni­ty — 7 Game­Con­trol and Timer Scripts

Descripción del objetivo

El pro­totipo es un juego en primera per­sona, en el cual el esce­nario es un laber­in­to. Den­tro del laber­in­to habrá un obje­to escon­di­do que se debe encon­trar antes de que se acabe el tiempo.

Aho­ra vamos a resolver la parte en la que el tiem­po se aca­ba. Creare­mos un Script que se encar­gará de lle­var la cuen­ta del tiem­po que transcurre. 

El Timer comen­zará la cuen­ta atrás des­de un val­or de min­u­tos y segun­dos que indi­care­mos en el inspec­tor, esto quiere decir que cada segun­do de reloj debe­mos actu­alizar la información.

El Script Timer además se encar­gará de mod­i­ficar el val­or del ele­men­to tex­to del Can­vas (parte supe­ri­or en figu­ra 1).

Cuan­do la cuen­ta del tiem­po llegue a cero, el Script Timer eje­cu­tará el méto­do EndGame del Script Game­Con­trol, de esta for­ma el juego ter­mi­nará y regre­sare­mos al menú principal.

escena en unity, en la parte superior un objeto texto que mostrara el tiempo
Fig. 1: Se bus­ca con­tro­lar el tex­to de la parte supe­ri­or para que muestre el tiem­po restante.

Resolución

Comen­zamos cre­an­do el Script Timer y lo abri­mos en el edi­tor. Vamos a ase­gu­rarnos de incluir el name­space UnityEngine.UI en la parte supe­ri­or del Script (figu­ra 3). De esta for­ma podremos acced­er a los obje­tos y méto­dos para imple­men­tar una inter­faz de usuario.

nuevo script c# llamado timer en unity
Fig. 2: Se crea un nue­vo Script C# de nom­bre Timer.

paquetes importados en el script timer
Fig. 3: Nos ase­gu­ramos de impor­tar UnityEngine.UI para acced­er a los méto­dos de la inter­faz de usuario.

Campos y variables

Para resolver la fun­cional­i­dad del Timer en c# nece­si­ta­mos con­tar con una serie de variables.

En la figu­ra 4 vemos que se uti­liza [Seri­al­ize­Field], esto sim­ple­mente hará que podamos ver y edi­tar estos cam­pos en el inspector.

Los dos enteros seri­al­iza­dos (min­utes y sec­onds) son los val­ores ini­ciales en los que empezará la cuen­ta regresiva.

Mien­tras que los dos enteros pri­va­dos (m y s) los usare­mos para lle­var la cuen­ta del tiempo.

campos definidos en script timer
Fig. 4: Defin­i­mos algunos cam­pos para que el timer pue­da cumplir su función.

Además nece­si­ta­mos un obje­to tipo Text para guardar la ref­er­en­cia de la com­po­nente Text del Can­vas que ten­emos que modificar.

Selec­cionamos el obje­to Con­trol de la jer­ar­quía y le asig­namos el Script Timer. Podemos obser­var los cam­pos seri­al­iza­dos del Script Timer, min­utes, sec­onds y timer­Text.

unity ventana inspector mostrando componentes de gameobjects
Fig. 5: Asig­namos el Script Timer al GameOb­ject Con­trol de la jerarquía.

jerarquia de un proyecto en unity
Fig. 6: Tomamos el GameOb­ject Timer y lo lle­va­mos al cam­po Timer­Text de la figu­ra anterior.

Vamos a escribir un min­u­to y cin­co segun­dos para el ini­cio de la cuen­ta regre­si­va. Luego tomamos el GameOb­ject Timer de la jer­ar­quía (que con­tiene una com­po­nente Text, figu­ra 6) y lo arras­tramos al cam­po timerText.

unity ventana inspector mostrando componentes de gameobjects
Fig. 7: Escribi­mos val­ores para ini­cializar las variables.

En la figu­ra 7 obser­va­mos que en el cam­po timer­Text se ha recono­ci­do una com­po­nente tipo Text.

Métodos a implementar

Tenien­do en mente cómo fun­ciona un Timer, sur­gen algu­nas ideas de posi­bles méto­dos. Primero para que el Timer comience a fun­cionar eje­cutare­mos un méto­do lla­ma­do Start­Timer. Luego otro méto­do que se eje­cute en inter­va­l­os de a un segun­do que es el que se va a encar­gar de los cál­cu­los, lo lla­mare­mos Update­Timer. Un ter­cer méto­do para deten­er el Timer, que se eje­cu­tará cuan­do este ter­mine de con­tar, este será Stop­Ti­mer.

como hacer un timer en unity con invoke
Fig. 8: Elim­i­namos el méto­do Update y creamos nuevos méto­dos para resolver el problema.

Por últi­mo un méto­do que se encar­gue de mod­i­ficar lo que se está mostran­do en la inter­faz de usuario, este méto­do se lla­mará Write­Timer y tomará como parámet­ros dos enteros para los min­u­tos y segun­dos que debe escribir en la inter­faz gráfica.

Si no estás muy famil­iar­iza­do con qué es un méto­do en pro­gra­mación en mi canal hay un video que podría ser útil, tam­bién escribí un artícu­lo para la sec­ción de apren­der a pro­gra­mar.

metodo en c# para escribir un timer
Fig. 9: Agreg­amos tam­bién un méto­do para escribir el Timer.

Noten que los parámet­ros que requiere este méto­do tienen exac­ta­mente el mis­mo nom­bre que los dos enteros definidos pre­vi­a­mente, que se encar­gan de lle­var la cuen­ta del Timer. 

Esto está hecho así a propósi­to para hablar un poco sobre con­tex­tos, prob­a­ble­mente para más ade­lante en otro artículo.

Instrucciones para los métodos

Método UpdateTimer

Hemos prop­uesto algunos méto­dos de man­era intu­iti­va con­sideran­do a grandes ras­gos el fun­cionamien­to del Timer, aho­ra debe­mos rel­lenar esos méto­dos con instruc­ciones C# que son las que harán el trabajo.

El méto­do Update­Timer se encar­gará de restar un segun­do, chequear si el tiem­po no se agotó, y mod­i­ficar los min­u­tos apropi­ada­mente. Final­mente uti­lizará el méto­do Write­Timer pasán­dole los val­ores de min­u­tos y segun­dos. En la figu­ra 10 vemos un ejem­p­lo de cómo imple­men­tar esto.

como hacer un timer en unity con invoke
Fig. 10: Instruc­ciones cor­re­spon­di­entes al méto­do UpdateTimer.

En la primera instruc­ción del méto­do dis­minuimos en una unidad la vari­able segun­dos, luego chequeamos si esta vari­able es neg­a­ti­va, es decir si pre­vi­a­mente valía 0 y aho­ra vale ‑1.

Si esto pasa nos fijamos si la vari­able de los min­u­tos vale 0, si es ver­dadero esto sig­nifi­ca que el tiem­po del Timer se agotó (dejo el comen­tario //endGame en esa región). Si los min­u­tos no son iguales a cero, dis­minuimos en una unidad la vari­able min­u­tos y hace­mos que la vari­able segun­dos val­ga 59.

Final­mente eje­cu­ta­mos el méto­do Write­Timer pasan­do las vari­ables m y s como parámetros.

Método WriteTimer

Este méto­do se va a encar­gar de mod­i­ficar el objec­to Text que habíamos definido. Depen­di­en­do de si la vari­able tiene un solo dígi­to (es decir es menor a 10) o tiene dos dígi­tos (may­or o igual a 10), vamos a eje­cu­tar las instruc­ciones que se ven en la figu­ra 11.

Lo que se hace es con­cate­nar una serie de strings o cade­nas de tex­to, en el caso de que s sea menor a 10, con­cate­n­amos un 0 delante de los segun­dos para que con­serve el for­ma­to de dos números.

Hay otras for­mas de hac­er esto como estable­cer un for­ma­to para las cade­nas de tex­to, pero de esta for­ma aprovechamos para ver cómo fácil­mente podemos con­cate­nar tex­to usan­do el oper­ador suma.

seria de instrucciones en c# para refrescar el valor de un timer
Fig. 11: Instruc­ciones cor­re­spon­di­entes al méto­do WriteTimer.

Método StartTimer

Este méto­do realizará la ini­cial­ización del Timer, es decir tomamos las vari­ables de min­u­tos y segun­do que aparecían en el inspec­tor con los val­ores ini­ciales y las asig­namos a las vari­ables m y s que lle­van la cuenta. 

Se eje­cu­ta el méto­do para escribir los val­ores en la inter­faz gráfica.

Final­mente uti­lizamos el méto­do Invoke, dan­do como parámet­ros el string "update­Timer", el cual es el nom­bre del méto­do y el segun­do parámetro es 1f que rep­re­sen­ta un segun­do. Esto hará que el méto­do update­Timer se eje­cute luego de un segundo.

seria de instrucciones en c# para iniciar un timer
Fig. 12: Instruc­ciones cor­re­spon­di­entes al méto­do Start­Timer. Invo­cación de updateTimer.

Vamos a agre­gar esta mis­ma instruc­ción al final del méto­do update­Timer, de esta for­ma el méto­do se va a auto invo­car cada un segun­do. Esto tam­bién se puede hac­er uti­lizan­do el méto­do Invok­eRe­peat­ing en lugar de Invoke.

como hacer un timer en unity con invoke
Fig. 13: El méto­do update­Timer se invo­ca a sí mis­mo cada un segundo.

Para ver más sobre el méto­do Invoke te invi­to a leer el artícu­lo de la serie fun­da­men­tal de Uni­ty en el que hace­mos que una máquina expende­do­ra nos entregue una lata luego de un tiem­po, tam­bién puedes ver el video aquí.

Interacciones entre Scripts

El Timer es como un apara­to que cumple su fun­ción, podemos con­fig­u­rar­lo, pon­er­lo a cor­rer y deten­er­lo. Tenien­do esto en mente vamos a hac­er que el Script Game­Con­trol sea el que con­t­role el Timer, pudi­en­do ini­cia­r­lo y deten­er­lo uti­lizan­do sus méto­dos públicos.

Primero vamos a definir un obje­to tipo Timer para usar en el Script GameControl.

Luego en el méto­do Start encon­tramos la ref­er­en­cia de Timer que está asig­na­do al mis­mo GameOb­ject Con­trol de la jer­ar­quía (jer­ar­quía en figu­ra 6). 

script para controlar el juego
Fig. 14: Agreg­amos un obje­to tipo Timer a los cam­pos del Script Game­Con­trol. Encon­tramos ref­er­en­cia en méto­do Start.

En la figu­ra 14 vemos sub­rayadas, la declaración de este obje­to Timer y cómo encon­tramos la ref­er­en­cia en el méto­do Start.

Aho­ra el Script Game­Con­trol tiene la ref­er­en­cia de la instan­cia del Script Timer, esto sig­nifi­ca que podrá acced­er a sus méto­dos y cam­pos públi­cos usan­do el oper­ador punto.

En el méto­do StartGame de Game­Con­trol vamos a hac­er que el Timer comience a trabajar. 

metodo start game del script que controla el juego
Fig. 15: En el méto­do startGame eje­cu­ta­mos el méto­do start­Timer de Timer.

Para­le­la­mente, tam­bién quer­e­mos que el Timer ten­ga algu­na man­era de avis­ar­le al Script Game­Con­trol que se acabó el tiem­po, por lo tan­to tam­bién nece­si­ta­mos la ref­er­en­cia del obje­to Game­Con­trol den­tro del Script Timer.

En la figu­ra 16 vemos la declaración de este obje­to y cómo se encuen­tra la ref­er­en­cia den­tro del méto­do Start.

fragmento del timer en c#
Fig. 16: Agreg­amos un obje­to tipo Game­Con­trol en Timer y encon­tramos la ref­er­en­cia en Start.

Por aho­ra vamos a hac­er que cuan­do se acabe el tiem­po el juego ter­mine y regre­se­mos al menú prin­ci­pal, es decir lo mis­mo que ocur­riría si apre­ta­mos la tecla Escape. Esto podemos lograr­lo eje­cu­tan­do el méto­do EndGame de GameControl.

En videos ante­ri­ores lo habíamos declar­a­do con vis­i­bil­i­dad pri­va­da, lo que impli­ca este méto­do no puede ser eje­cu­ta­do des­de un con­tex­to exter­no, por ejem­p­lo el Script Timer.

Para que podamos eje­cu­tar­lo des­de el Script Timer cam­bi­amos a vis­i­bil­i­dad públi­ca. Ver fig­uras 17 y 18.

visibilidad privada de un metodo, no accesible desde otro contexto
Fig. 17: Obser­va­mos que la vis­i­bil­i­dad del méto­do EndGame es pri­va­da, por eso no podemos eje­cu­tar­lo des­de Timer.

visibilidad publica de un metodo, accesible desde otro contexto
Fig. 18: Cam­bi­amos la vis­i­bil­i­dad a públi­co para que sea acce­si­ble des­de otro contexto.

Aho­ra si, en la región de Update­Timer en la que detec­ta­mos que la cuen­ta lle­ga a cero (habíamos deja­do el comen­tario //endGame), eje­cu­ta­mos el méto­do EndGame del Script Game­Con­trol y luego la sen­ten­cia return para ter­mi­nar la eje­cu­ción del méto­do UpdateTimer.

como hacer un timer en unity con invoke
Fig. 19: Iden­ti­fi­camos la región del códi­go en la que se ha ago­ta­do el tiem­po y eje­cu­ta­mos el méto­do EndGame.

En el méto­do EndGame del Script Game­Con­trol vamos a deten­er el Timer, como se obser­va en la figu­ra 20.

¿Por qué no hici­mos que el méto­do Update­Timer pro­duz­ca la deten­ción del Timer cuan­do la cuen­ta lle­ga a cero?

Se pudo haber hecho de muchas for­mas dis­tin­tas, en su momen­to opté por hac­er­lo así tenien­do en mente que el Timer solo cumple la fun­ción de lle­var la cuen­ta del tiem­po y avis­ar cuan­do el tiem­po se aca­ba, luego el Script Game­Con­trol que uti­liza el Timer decide qué hac­er con él.

metodo c# unity que se encarga de detener el juego
Fig. 20: En el méto­do EndGame eje­cu­ta­mos la acción para deten­er el Timer.

Método StopTimer

En este méto­do sólo vamos a can­ce­lar todas las invo­ca­ciones que puedan estar pen­di­entes, tam­bién podríamos resetear los val­ores del tem­po­rizador a los val­ores iniciales.

Como obser­vación, en el códi­go de la figu­ra 19 si el Timer lle­ga a cero, se eje­cu­ta el méto­do EndGame y pos­te­ri­or­mente return, quiere decir que no hay ningu­na invo­cación de update­Timer pen­di­ente y en ese caso la instruc­ción Can­celIn­voke() no sería necesaria.

Pero podría ser que eje­cute­mos el méto­do EndGame debido a otras razones, por ejem­p­lo apre­tar la tecla Escape o el jugador gana la par­ti­da, en ese caso si es nece­sario can­ce­lar las invo­ca­ciones de UpdateTimer.

metodo para detener un timer en c#
Fig. 21: En el méto­do Stop­Ti­mer can­ce­lam­os las invo­ca­ciones que puedan estar pendientes.

Pruebas finales

Voy a ase­gu­rarme de que fun­cione como se espera, primero voy a colo­car como val­ores ini­ciales 0 min­u­tos 5 segun­dos y entro en el modo juego.

unity ventana inspector mostrando componentes de gameobjects
Fig. 22: Con­fig­uro los val­ores ini­ciales para obser­var ráp­i­da­mente los resultados.

Al entrar en el modo juego el Timer comien­za con 5 segun­dos, hace la cuen­ta regre­si­va y al lle­gar a 0 vemos en la figu­ra 24 que vuelve al menú principal.

escena en unity que funciona como menu principal, boton para empezar el juego
Fig. 23: Entramos en el modo juego para pro­bar el fun­cionamien­to de la cuen­ta regresiva.

escena en unity, en la parte superior un objeto texto que muestra el valor del timer en c#
Fig. 24: Al ago­tarse el tiem­po, el resul­ta­do es el mis­mo que apre­tar la tecla Escape, se eje­cu­ta el méto­do EndGame y volve­mos al menú principal.

Aho­ra ver­i­fi­camos que se respete el for­ma­to de dos números para los segun­dos y que se decre­menten cor­rec­ta­mente los min­u­tos cuan­do los segun­dos pasan de cero a 59. Ini­ci­amos el Timer con 10 min­u­tos 5 segun­dos y entramos en el modo juego.

Obser­va­mos que se respe­ta el for­ma­to de dos dígi­tos para los segun­dos y además los min­u­tos se decre­men­tan cor­rec­ta­mente. El ejer­ci­cio está terminado.

escena en unity, en la parte superior un objeto texto que muestra el valor del timer en c#
Fig. 25: Probamos nue­va­mente con el timer en 10 min­u­tos 5 segun­dos.
escena en unity, en la parte superior un objeto texto que muestra el valor del timer en c#
Fig. 26: Se respe­ta el for­ma­to de la cuen­ta regresiva.

Conclusión

Hemos vis­to cómo crear un tem­po­rizador sim­ple en Uni­ty, que cumple la fun­ción de lle­var la cuen­ta del tiem­po, mostrar­la en la inter­faz de usuario y cuan­do el tiem­po se ago­ta infor­mar al Script Game­Con­trol para que deci­da qué hacer.

Este tem­po­rizador se pudo haber imple­men­ta­do de varias for­mas dis­tin­tas, en este caso usamos el méto­do Invoke porque me pare­ció una alter­na­ti­va bas­tante simple.

Vimos como podemos mod­i­ficar fácil­mente una com­po­nente tex­to del Can­vas siem­pre que con­te­mos con su ref­er­en­cia, por lo tan­to podemos uti­lizar esto para hac­er otras cosas como mostrar el pun­ta­je, men­sajes de infor­ma­ción, etc.

En este ejer­ci­cio están implíc­i­tos los con­cep­tos de clase y obje­to de pro­gra­mación, el Script Timer es una clase que con­tiene cam­pos y méto­dos para resolver un prob­le­ma en par­tic­u­lar, cuen­ta con la ref­er­en­cia a otros obje­tos como Game­Con­trol para poder enviar­le men­sajes cuan­do lo necesite.

Deja un comentario

Tu dirección de correo electrónico no será publicada.

Scroll al inicio
Secured By miniOrange