🎮 UnityDocs

Eventos y delegados en Unity

Cómo hacer que unas partes del juego avisen a otras sin acoplarse, usando delegados, Action, C# events y UnityEvent. La base de un código desacoplado y mantenible.

📄 ArtículoAvanzado✅ RevisadoUnity 6.0 LTSActualizado 2026-07-14
DificultadConceptual Código Matemáticas
Tiempo📖 Lectura 9 min · ⌨️ Práctica 25 min

El problema que resuelven#

Cuando el jugador muere, muchas cosas deben reaccionar: la UI muestra "Game Over", el audio para la música, el marcador se guarda, los enemigos se detienen. La forma ingenua es que el script del jugador llame a todos:

C#
// ❌ El jugador conoce a TODOS: acoplamiento máximo
uiManager.MostrarGameOver();
audioManager.PararMusica();
scoreManager.Guardar();

Si mañana añades un sistema nuevo, tienes que volver a tocar el jugador. Los eventos invierten esto: el jugador solo anuncia "he muerto", y cada sistema decide si escucha. El jugador no conoce a nadie.

Delegados: la base#

Un delegado es una variable que guarda una función. Puedes pasarla, almacenarla y llamarla. C# trae dos genéricos que cubren casi todo:

C#
Action saludar = () => Debug.Log("Hola");   // sin parámetros, no devuelve nada
Action<int> daño = (n) => Debug.Log("Daño: " + n);  // recibe un int
Func<int, int, int> sumar = (a, b) => a + b;        // recibe 2 int, devuelve int

saludar();            // Hola
daño(10);             // Daño: 10
int r = sumar(2, 3);  // 5

Eventos con event#

Un event es un delegado con reglas de seguridad: desde fuera solo puedes suscribirte (+=) o darte de baja (-=), pero no invocarlo ni borrar los demás suscriptores. Es el patrón observer del lenguaje.

C#
using System;
using UnityEngine;

public class Salud : MonoBehaviour
{
    // El evento que otros pueden escuchar
    public event Action<int> AlCambiarVida;
    public event Action AlMorir;

    private int vida = 100;

    public void RecibirDaño(int cantidad)
    {
        vida = Mathf.Max(0, vida - cantidad);
        AlCambiarVida?.Invoke(vida);   // avisa a los suscritos (si hay)
        if (vida == 0)
            AlMorir?.Invoke();
    }
}

Y quien quiera reaccionar, se suscribe:

C#
public class BarraDeVidaUI : MonoBehaviour
{
    [SerializeField] private Salud salud;

    void OnEnable()  => salud.AlCambiarVida += Actualizar;
    void OnDisable() => salud.AlCambiarVida -= Actualizar;   // ¡imprescindible!

    void Actualizar(int vida) => Debug.Log("Vida en UI: " + vida);
}
Suscribe en OnEnable, desuscribe en OnDisable

Si te suscribes y no te das de baja, cuando el objeto se destruya el evento seguirá teniendo una referencia a un método de un objeto muerto: fuga de memoria y posibles NullReferenceException. La pareja OnEnable/OnDisable es la forma segura y simétrica.

El operador ?.Invoke()#

AlMorir?.Invoke() significa "si hay alguien suscrito, avísale; si no, no hagas nada". Sin el ?., invocar un evento sin suscriptores lanza NullReferenceException. Es el patrón estándar para disparar eventos.

UnityEvent: eventos desde el Inspector#

UnityEvent es la versión de Unity que puedes conectar arrastrando en el Inspector, sin código. Es lo que usan los botones de UI (onClick).

C#
using UnityEngine;
using UnityEngine.Events;

public class Interruptor : MonoBehaviour
{
    public UnityEvent alActivar;   // aparece en el Inspector

    public void Activar() => alActivar.Invoke();
}
⚖️ Comparativa · C# event vs UnityEvent
event ActionUnityEvent
Se configura enCódigoInspector (o código)
RendimientoMejorAlgo mayor coste
Lo usan diseñadores sin programarNo
Ideal paraComunicación entre sistemas de códigoEnganchar acciones desde el editor

Cuándo NO usar eventos#

  • Para flujo lineal simple dentro de una misma clase: una llamada directa es más clara.
  • Si abusas, el flujo se vuelve difícil de seguir ("¿quién ha llamado a esto?"). Los eventos desacoplan, pero demasiados hacen el código "mágico".

Errores frecuentes#

  • No darse de baja (-=) y provocar fugas o llamadas a objetos destruidos.
  • Invocar sin ?. y petar cuando no hay suscriptores.
  • Usar UnityEvent en bucles calientes por comodidad, cuando un event sería más eficiente.

Ponte a prueba#

📝 Pon a prueba lo aprendido

Resumen#

Los eventos permiten que unos sistemas avisen a otros sin conocerlos: el emisor anuncia, los interesados se suscriben. Usa Action/event para comunicación en código (rápido) y UnityEvent para conectar acciones desde el Inspector. Suscríbete en OnEnable, da de baja en OnDisable e invoca siempre con ?.Invoke().

Fuentes y para profundizar