Hoy vamos a conocer en que consiste un “GameManager” en C# y Unity.
Uno de los pilares para construir juegos organizados y escalables en Unity es el uso de un GameManager. Este patrón te permite centralizar el control del estado del juego, facilitando la lógica de transiciones como: pantalla de inicio, pausa, juego activo, victoria o derrota.
En este tutorial aprenderás a:
- Crear un GameManager
- Usar enum para definir estados del juego
- Controlar el flujo con switch
- Activar/desactivar comportamientos según el estado
Tutorial de Unity Nivel: Principiante.
6.1 ¿Qué es un GameManager?
Un GameManager es un script que controla los aspectos globales del juego (no es un script predefinido o que venga por default con Unity, es un código que tu debes de crear según las necesidades de tu juego). Un “GameManager” ideal para:
- Controlar estados del juego
- Llevar el puntaje
- Manejar cambios de escena
- Coordinar eventos como victoria o derrota
Un GameManager tiene las siguientes caracteristicas:
- Responsabilidad única: controla el flujo global del juego.
- Singleton: suele implementarse para asegurar una única instancia accesible desde cualquier parte.
- Estados: define momentos como menú principal, partida en curso, pausa, fin de nivel, etc.
Piensa en un GameManager como el “director de orquesta” del juego.
6.2 Implementando un GameManager
¿Para qué nos sirve “enum”?
Un enum es un tipo de dato o enumeración de datos que nos permite nombrar un conjunto de constantes las cuales podrán usarse posteriormente con la finalidad de tener un código más ordenado y fácil de trabajar. En nuestro caso usaremos enum para definir los estados de nuestro juego:
Primero, creamos nuestro archivo de enum “EstadoJuego.cs”
// Archivo: EstadoJuego.cs public enum EstadoJuego { MenuPrincipal, Jugando, Pausado, Victoria, Derrota }
- Cada valor representa un “modo” distinto del juego.
- Facilita lecturas y mantenibilidad frente a “magic numbers” o cadenas.
- Tener el enum en un archivo separado mejora la claridad y permite reutilizarlo (por ejemplo, también podrías usarlo en un sistema de UI que reaccione a cambios de estado).
Ahora, creamos nuestro archivo “GameManager.cs”
using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { public static GameManager Instancia { get; private set; } public EstadoJuego EstadoActual { get; private set; } [Header("Referencias UI")] public GameObject panelMenu; public GameObject panelPausa; public GameObject panelVictoria; public GameObject panelDerrota; void Awake() { if (Instancia == null) { Instancia = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } void Start() { CambiarEstado(EstadoJuego.MenuPrincipal); } void Update() { // Permitir pausar/reanudar con ESC if (EstadoActual == EstadoJuego.Jugando && Input.GetKeyDown(KeyCode.Escape)) CambiarEstado(EstadoJuego.Pausado); else if (EstadoActual == EstadoJuego.Pausado && Input.GetKeyDown(KeyCode.Escape)) CambiarEstado(EstadoJuego.Jugando); } public void CambiarEstado(EstadoJuego nuevoEstado) { // Salida del estado anterior (si necesitas limpieza) switch (EstadoActual) { case EstadoJuego.Jugando: Time.timeScale = 1f; break; case EstadoJuego.Pausado: Time.timeScale = 0f; break; } EstadoActual = nuevoEstado; // Entrada al nuevo estado switch (EstadoActual) { case EstadoJuego.MenuPrincipal: Time.timeScale = 0f; MostrarPaneles(menu: true); break; case EstadoJuego.Jugando: Time.timeScale = 1f; MostrarPaneles(); break; case EstadoJuego.Pausado: Time.timeScale = 0f; MostrarPaneles(pausa: true); break; case EstadoJuego.Victoria: Time.timeScale = 0f; MostrarPaneles(victoria: true); break; case EstadoJuego.Derrota: Time.timeScale = 0f; MostrarPaneles(derrota: true); break; } } private void MostrarPaneles(bool menu = false, bool pausa = false, bool victoria = false, bool derrota = false) { panelMenu?.SetActive(menu); panelPausa?.SetActive(pausa); panelVictoria?.SetActive(victoria); panelDerrota?.SetActive(derrota); } // Métodos públicos para UI public void BotonIniciar() { // Si usas varias escenas, podrías cargar aquí la escena de juego // SceneManager.LoadScene("Nivel1"); CambiarEstado(EstadoJuego.Jugando); } public void BotonReintentar() { // Recarga la escena actual SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); } public void BotonSalir() { Application.Quit(); } }
Explicación:
- Singleton: Instancia para acceder globalmente.
- Time.timeScale: pausa o reanuda toda la simulación.
- switch: controla “salida” del estado anterior y “entrada” al nuevo.
- MostrarPaneles(): activa/desactiva UI según estado.
- Métodos UI: botones enlazados en el Inspector.
- public EstadoJuego EstadoActual { get; private set; } expone el estado actual de lectura pública y escritura restringida al mismo GameManager.
- DontDestroyOnLoad, hace que tu GameManager persiste al cambiar de escena.
Ahora, veamos que sucede si tenemos otro script que también necesite interactuar con nuestro GameManager.
Supongamos que tenemos el script que controla a nuestro personaje principal (PlayerController.cs)
using UnityEngine; public class PlayerController : MonoBehaviour { public int vida = 3; void Update() { // Solo permitir movimiento si el juego está en estado Jugando if (GameManager.Instancia.EstadoActual != EstadoJuego.Jugando) return; // Lógica de movimiento, disparo, etc. } public void RecibirDaño(int cantidad) { vida -= cantidad; if (vida <= 0) GameManager.Instancia.CambiarEstado(EstadoJuego.Derrota); } }
Y que tenemos otro script para controlar la UI (UIController.cs)
using UnityEngine; using UnityEngine.UI; public class UIController : MonoBehaviour { public Button btnIniciar, btnReintentar, btnSalir, btnPausa; void Start() { btnIniciar.onClick.AddListener(GameManager.Instancia.BotonIniciar); btnReintentar.onClick.AddListener(GameManager.Instancia.BotonReintentar); btnSalir.onClick.AddListener(GameManager.Instancia.BotonSalir); btnPausa.onClick.AddListener(() => { if (GameManager.Instancia.EstadoActual == EstadoJuego.Jugando) GameManager.Instancia.CambiarEstado(EstadoJuego.Pausado); }); } }
6.3 Conclusión
Un buen GameManager es esencial para mantener la estructura lógica y flujo de estados de tu juego bajo control. Gracias al uso de enum y switch, puedes manejar cada transición de forma limpia, clara y escalable.
Ya sea un juego pequeño o una producción compleja, tener un GameManager bien diseñado es un paso profesional.
Implementar un GameManager con enum y switch te ofrece:
- Claridad: todos los estados en un solo lugar.
- Escalabilidad: añadir nuevos estados sin ensuciar el código.
- Facilidad de mantenimiento: cambios centralizados.
- Control de flujo: pausa, reinicios, transiciones y UI coordinadas.
- Tu proyecto en Unity estará mejor estructurado y preparado para crecer sin enredos ni “spaguetti code”.
- Se puede usar para pausar IA, físicas, música, etc.
- Compatible con eventos y sistemas más avanzados (como FSM o ScriptableObjects)
Buenas prácticas:
- Usa Singleton para que el GameManager sea accesible globalmente.
- Usa Time.timeScale para pausar la acción del juego.
- No pongas todo el código del juego dentro del GameManager, solo el flujo.
- Combínalo con eventos o FSMs para proyectos grandes.
- Separar UI: no embebas lógica de juego en el GameManager. Usa métodos públicos para UI.
- Desacoplar responsabilidades: GameManager gestiona estados, otros scripts gestionan lógica específica.
- Evitar lógica pesada en Update: delega comportamientos a componentes o máquinas de estados.
- Extender con eventos: puedes disparar OnEstadoCambiado (delegate/event) para que otros sistemas reaccionen. Por ejemplo:
public event Action<EstadoJuego> OnEstadoCambiado; ... OnEstadoCambiado?.Invoke(EstadoActual);
- Multi–Scene: con DontDestroyOnLoad, tu GameManager persiste al cambiar de escena.
Ejercicios.
Para reforzar lo aprendido, es necesario practicarlo, por ello intenta realizar los siguientes ejercicios:
- Siguiendo los ejemplos de este tutorial, crea tu propio GameManager que permita controlar los estados de tu juego (crea un contador con temporizador para que puedas ver como se detiene y vuelve a activarse).
Este Tutorial de Unity termina aquí. Acompáñanos en el siguiente tutorial donde veremos “Scriptable Objects”.
Siguiente Tutorial de Unity: “7. ScriptableObjects en Unity“
Unity Tutorial: “C# en Unity 2“
1. Los Métodos Clave de Unity
2. Herencia
3. Encapsulamiento y Constructores
4. Corrutinas en Unity
5. Delegados y Eventos
6. GameManager y Control de Flujo
7. ScriptableObjects en Unity
8. El Patrón Factory
9. Máquinas de Estado en Unity
10. Gestionando nuestro Código
Ver más Tutoriales