jairogarcíarincón

05/09/2022
Contenidos
Introducción
En esta receta, veremos cómo crear una interfaz de usuario UI que muestre contadores de coleccionables, vidas, y tiempo a nuestro juego.
Además, añadiremos la lógica necesaria para mostrar el tiempo transcurrido en el juego y mensajes a medida que se produzcan ciertos eventos.
Puedes comprobar el objetivo final haciendo clic AQUÍ.
Creación del escenario
Tomaremos como punto de partida la receta 3, ya que en la próxima receta añadiremos los elementos y la lógica necesaria para recoger los coleccionables y premios de nuestro juego.
A partir de la receta 3 y en la escena Juego, vamos a crear un Canvas con los siguientes elementos:
- Un UI > Text con el nombre Texto Monedas
- Un UI > Text con el nombre Texto Tiempo
- Un UI > Text con el nombre Mensajes
- Un UI > Text con el nombre Vidas
Utiliza los conocimientos adquiridos en las recetas anteriores para crear tu propia versión, pero inicialmente la interfaz de usuario se debería parecer a esto:

El tiempo transcurrido
Para mostrar los diferentes valores, vamos a añadir las siguientes variables públicas para poder compartirlas con el resto de escenas, al inicio del script de GameManager (antes del método Start):
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Añadir en la declaración de variables de GameManager */ | |
//Variables compartidas en todas las escenas | |
public float tiempo = 0; //Para contabilizar el tiempo | |
public bool isJuego = true; //Para saber si estoy jugando y que se incremente el tiempo cuando entre en la escena de Juego | |
public int vidas = 3; //para contabilizar las vidas | |
public int monedas = 20; //para contabilizar las monedas restantes |
A continuación, crearemos un script llamado Tiempo con el siguiente código:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class Tiempo : MonoBehaviour { | |
//Variable para asociar el objeto Texto Tiempo | |
public Text textoTiempo; | |
//Script GameManager | |
private GameManager gameManager; | |
void Start () { | |
//Inicializo el texto del contador de tiempo | |
textoTiempo.text = "Tiempo: 00:00"; | |
//Capturo el script de GameManager | |
gameManager = FindObjectOfType<GameManager>(); | |
} | |
void Update () { | |
//Escribo tiempo transcurrido (si no se ha acabado el juego) | |
if (gameManager.isJuego){ | |
textoTiempo.text = "Tiempo: " + formatearTiempo(); | |
} | |
} | |
//Formatear tiempo (público porque la necesitaremos más adelante) | |
public string formatearTiempo(){ | |
//Añado el intervalo transcurrido a la variable tiempo | |
if (gameManager.isJuego){ | |
gameManager.tiempo += Time.deltaTime; | |
} | |
//Formateo minutos y segundos a dos dígitos | |
string minutos = Mathf.Floor(gameManager.tiempo / 60).ToString("00"); | |
string segundos = Mathf.Floor(gameManager.tiempo % 60).ToString("00"); | |
//Devuelvo el string formateado con : como separador | |
return minutos + ":" + segundos; | |
} | |
} |
Para que funcione, en la escena de Juego, debemos aplicar el script al Canvas y asociar el objeto Texto Tiempo a la variable Texto Tiempo del script.
NOTA: A partir de ahora, dado que estamos utilizando variables del GameManager, siempre debemos iniciar el juego desde la escena Preload.
Las vidas
En esta receta, consideraremos que el Jugador comienza con 3 vidas y pierde una cada vez que se sale del Suelo. Esto ocurrirá, al menos en mi caso, cuando el jugador caiga por debajo de 0 en el eje Y (Para comprobarlo en tu caso, mueve el Jugador y comprueba los valores de Position).
Puesto que es el Jugador el que pierde vidas, añadiremos el código necesario en JugadorController, aunque haciendo referencia a variables del GameManager:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Añadir en las librerías que se importan al principio del script */ | |
using UnityEngine.UI; | |
/* Añadir en la declaración de variables de JugadorController */ | |
//Límite en Y del Suelo | |
int limiteSuelo = 0; | |
//Script GameManager | |
private GameManager gameManager; | |
//Variable para asociar el objeto Texto Vidas | |
public Text textoVidas; | |
//variable para la posición inicial del jugador | |
Vector3 posicionInicial; | |
/* Añadir en el método Start() */ | |
//Busco y asocio mi script de GameManager | |
gameManager = FindObjectOfType<GameManager>(); | |
//Inicializo el texto del contador de vidas | |
textoVidas.text = "Vidas: " + gameManager.vidas; | |
//Capturo la posición inicial del jugador para cuando pierda una vida poder reposicionarlo | |
posicionInicial = transform.position; | |
/* Añadir en el método FixedUpdate() */ | |
//Si ha caído por debajo del suelo, le quito una vida | |
if (transform.position.y < limiteSuelo) quitarVida(); | |
/* Añadir este método al final de la clase (antes de la llave } de cierre) */ | |
//Quito una vida y muevo al jugador a la posición inicial | |
void quitarVida(){ | |
//Resto una vida | |
gameManager.vidas--; | |
//Actualizo el contador de vidas | |
textoVidas.text = "Vidas: " + gameManager.vidas; | |
//Devuelvo el Jugador a su posición inicial y le quito la fuerza | |
transform.position = posicionInicial; | |
rb.velocity = Vector3.zero; | |
} |
Para que funcione, lo único que debemos hacer es asociar el objeto Texto Vidas la variable Texto Vidas.
Mensajes
Como habrás podido apreciar, con el código anterior se van restando vidas al Jugador pero el juego no termina nunca. Además, el texto del Mensaje está siempre presente en la pantalla.
Para finalizar la receta, añadiremos la siguiente lógica:
- Ocultar al inicio el texto de Mensajes
- Comprobar que el Jugador tiene vidas disponibles.
- Mostrar un mensaje de juego terminado si no tiene vidas.
- Impedir que el jugador se siga moviendo.
- Parar el contador de Texto Tiempo.
Nota: Añadiremos la lógica del Texto Coleccionables en la próxima receta.
Para conseguir los 4 primeros objetivos, modificaremos el código de JugadorController. Observa que hemos incorporado el método moverJugador() y hemos trasladado a él toda la lógica relacionada con el movimiento del Jugador. Esto es para poder quitar el movimiento al Jugador cuando se quede sin vidas de una forma más optimizada:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Añadir en la declaración de variables */ | |
//Variable para asociar el objeto Mensajes | |
public Text textoMensajes; | |
/* Añadir en el método Start() */ | |
//Inicio el texto de mensajes a vacío | |
textoMensajes.text = ""; | |
/* Sustituir el método FixedUpdate() por el siguiente */ | |
void FixedUpdate () { | |
//Si quedan vidas | |
if (gameManager.vidas > 0){ | |
//Muevo el jugador (si tiene vidas) | |
moverJugador(); | |
//Si ha caído por debajo del suelo, le quito una vida | |
if (transform.position.y < limiteSuelo) quitarVida(); | |
} | |
//Si no quedan vidas | |
else{ | |
//Muestro mensaje | |
textoMensajes.text = "Juego Terminado"; | |
//Pongo isJuego a false para que deje de contar el script Tiempo | |
gameManager.isJuego = false; | |
} | |
} | |
/* Añadir el método moverJugador() antes de la llave de cierre } de la clase */ | |
//Lógica necesaria para mover al jugador | |
void moverJugador(){ | |
//Capturo el movimiento en horizontal y vertical de nuestro teclado | |
float movimientoH = Input.GetAxis("Horizontal"); | |
float movimientoV = Input.GetAxis("Vertical"); | |
//Genero el vector de movimiento asociado, teniendo en cuenta la velocidad | |
Vector3 movimiento = new Vector3(movimientoH * velocidad, 0.0f, movimientoV * velocidad); | |
//Aplico ese movimiento al RigidBody del jugador | |
rb.AddForce(movimiento); | |
//Si pulsa el botón de saltar y está en el suelo | |
if (Input.GetButton("Jump") && isSuelo()){ | |
//Aplico el movimiento vertical con la potencia de salto | |
rb.velocity += Vector3.up * salto; | |
} | |
} |
Para que funcione, lo único que falta es asociar el objeto Mensajes la variable Texto Mensajes.
Con esto estaría terminada la receta, aunque todavía quedaría pendiente cambiar a la escena de Créditos y mostrar un resumen del juego, algo que haremos más adelante como ejercicio propuesto, pero que puedes ir planteando hacer por tu cuenta.
Publicado el 29 de Junio de 2025
unity