Pantalla de pausa con reseteo de escena en Unity

Resumen

Pausar un juego en Unity no es solo congelar la acción: implica orquestar estados, conectar botones y limpiar la escena para que todo regrese a su lugar. Aquí construyes la lógica de pantalla de pausa en Unity integrándola con un Game Manager basado en estados, dos botones funcionales y un reseteo limpio del tablero y la cámara.

Esta guía es para ti si estás desarrollando un juego match-3 o cualquier proyecto en Unity donde necesites manejar transiciones entre estados de juego sin que queden objetos huérfanos en escena.

¿Cómo agregar un estado de pausa al Game Manager?

El primer paso es ampliar el enum de estados del Game Manager para que reconozca la pausa como una situación válida del juego [00:34].

Dentro del enum GameState que ya contiene idle, levelSelection, inGame y gameOver, agregas un nuevo valor llamado pause. Con ese estado disponible, creas dos funciones públicas:

  • public void Pause(): cambia el gameState a GameState.pause y dispara OnGameStateUpdated para notificar a los suscriptores.
  • public void ContinueGame(): vuelve el estado a inGame y notifica de nuevo, sin reiniciar puntos ni tiempo.

¿Por qué no usar StartGame para reanudar? Porque StartGame reinicia los puntos a cero. ContinueGame preserva el progreso y solo cambia el estado.

Esta separación entre iniciar y continuar es clave en el patrón de máquina de estados: cada función tiene una sola responsabilidad.

¿Cómo conectar el botón de pausa con la UI?

El botón de pausa vive en la UI In Game, y su trabajo es invocar al singleton del Game Manager [01:38].

En el script UIInGame, donde antes había un comentario reservado, ahora llamas a GameManager.instance.Pause(). Con eso el sistema de eventos hace el resto: la pantalla de pausa se vuelve visible porque está suscrita al cambio de estado.

¿Cómo configurar el componente UI Screen para la pausa?

A la pantalla de pausa que ya tenías desactivada le agregas el componente UIScreen con esta configuración:

  • Estado visible: pause.
  • Tiempo de transición: 0.3 segundos.
  • Container Rect y Container Canvas: el contenedor principal (al que le añades un CanvasGroup si no lo tiene).
  • Background: la imagen de fondo.
  • Visible Alpha: 0.8, igual que la pantalla de inicio.

Este patrón reutilizable te permite que cualquier pantalla nueva se enganche al sistema con solo declarar en qué estado debe mostrarse.

¿Cómo programar los botones de continuar y salir?

Ahora necesitas un script dedicado que maneje los dos botones de la pantalla de pausa [03:00].

Creas un nuevo script de C# llamado UIPause. No requiere Start ni Update, solo dos métodos públicos:

csharp public void ContinueButtonPressed() { GameManager.instance.ContinueGame(); }

public void ExitButtonPressed() { GameManager.instance.ExitGame(); }

El método ExitGame es el mismo que ya usabas en el botón de salir de la pantalla de Game Over, así que reaprovechas código.

Después asignas el script al objeto UIPause con Add Component, y en el inspector arrastras la referencia a cada botón conectando los eventos OnClick: el botón continuar dispara ContinueButtonPressed y el botón exit dispara ExitButtonPressed.

¿Qué hace el botón de exit? Llama a GameManager.instance.ExitGame(), la misma función del botón de Game Over, lo que cambia el estado a idle y devuelve al jugador a la pantalla inicial.

¿Por qué el tablero y la cámara quedan mal al salir del juego?

Al probar el flujo aparece un problema: la cuadrícula vieja sigue en escena y la cámara mantiene la posición y zoom del nivel jugado [04:53].

Esto pasa porque cuando creaste el tablero y moviste la cámara para encuadrar el nivel, esos cambios nunca se revirtieron. La solución vive en el script Board, que ya está suscrito a los cambios de estado.

¿Cómo resetear la cuadrícula y la cámara al volver al menú?

Dentro de OnGameStateUpdated del Board, agregas un nuevo if: si el nuevo estado es GameManager.GameState.idle, llamas a dos funciones nuevas, ResetBoard y ResetCamera, y devuelves el flag setupMade a false para que en la siguiente partida todo se construya desde cero.

El método ResetCamera reinicia dos propiedades de la cámara principal:

  • Camera.main.orthographicSize = 5.
  • Camera.main.transform.position = new Vector3(0, 0, 0).

El método ResetBoard elimina todos los tiles generados recorriendo los hijos del transform actual:

csharp foreach (Transform item in transform) { Destroy(item.gameObject); }

Aquí aprovechas que el transform padre en la jerarquía de Unity contiene como iterables todos los transforms hijos. Es una forma compacta de limpiar la escena sin mantener listas auxiliares.

¿Cómo se ve el flujo completo funcionando?

Con ResetCamera y ResetBoard ejecutándose cada vez que el estado vuelve a idle, el ciclo queda cerrado.

Das play, entras a selección de niveles, juegas, pausas, sales, y la pantalla de inicio aparece exactamente como la primera vez. Si vuelves a iniciar, el siguiente juego se construye limpio, sin rastros del anterior.

Este tipo de detalles, resetear estado al cambiar de pantalla, son los que diferencian un prototipo de un juego pulido. Cuéntame en los comentarios qué otros estados has agregado a tu Game Manager y cómo manejas las transiciones entre ellos.