🎮 UnityDocs

Sistema de vida y daño

Un sistema de salud reutilizable con una interfaz IDañable para que cualquier cosa reciba daño (jugador, enemigos, barriles) y eventos para conectar UI, efectos y muerte sin acoplar nada.

🍳 RecetaIntermedio✅ RevisadoUnity 6.0 LTSActualizado 2026-07-15
DificultadConceptual Código Matemáticas
Tiempo📖 Lectura 7 min · ⌨️ Práctica 25 min

El objetivo#

Un sistema de salud que puedas pegar a cualquier cosa (jugador, enemigo, caja rompible) y al que cualquier fuente de daño (espada, bala, trampa) pueda golpear sin conocer qué es. La clave: una interfaz y eventos.

Paso 1 — La interfaz IDañable#

C#
public interface IDañable
{
    void RecibirDaño(int cantidad);
}

Cualquier clase que la implemente "promete" tener RecibirDaño. La espada no preguntará "¿eres un enemigo?", sino "¿eres IDañable?".

Paso 2 — El componente de vida#

C#
using System;
using UnityEngine;

public class Salud : MonoBehaviour, IDañable
{
    [SerializeField] private int vidaMax = 100;
    public int VidaActual { get; private set; }

    // Eventos para conectar UI, efectos, sonido... sin acoplar
    public event Action<int, int> AlCambiar;  // (actual, max)
    public event Action AlMorir;

    private bool muerto = false;

    void Awake() => VidaActual = vidaMax;

    public void RecibirDaño(int cantidad)
    {
        if (muerto) return;

        VidaActual = Mathf.Clamp(VidaActual - cantidad, 0, vidaMax);
        AlCambiar?.Invoke(VidaActual, vidaMax);

        if (VidaActual == 0) Morir();
    }

    public void Curar(int cantidad)
    {
        if (muerto) return;
        VidaActual = Mathf.Clamp(VidaActual + cantidad, 0, vidaMax);
        AlCambiar?.Invoke(VidaActual, vidaMax);
    }

    void Morir()
    {
        muerto = true;
        AlMorir?.Invoke();   // que cada quien reaccione (UI, drop, animación)
    }
}

Paso 3 — Hacer daño desde cualquier fuente#

Una bala o un raycast golpea sin saber qué toca:

C#
void Impacto(Collider2D other)
{
    if (other.TryGetComponent<IDañable>(out var objetivo))
        objetivo.RecibirDaño(25);
}
Por qué la interfaz lo cambia todo

Mañana añades una PuertaReforzada o un Cristal que implementan IDañable, y la espada ya los daña sin tocar el código de la espada. Es el poder de programar contra un contrato en vez de contra tipos concretos. Ver herencia e interfaces.

Paso 4 — Conectar la UI (y todo lo demás)#

La barra de vida y cualquier otro sistema se suscriben a los eventos:

C#
void OnEnable()
{
    salud.AlCambiar += ActualizarBarra;
    salud.AlMorir   += MostrarGameOver;
}
void OnDisable()
{
    salud.AlCambiar -= ActualizarBarra;
    salud.AlMorir   -= MostrarGameOver;
}

El componente Salud no sabe que existe una barra, ni un game over, ni un sonido. Solo anuncia. Puedes enchufar y desenchufar reacciones libremente.

Extras habituales#

  • Invulnerabilidad temporal tras recibir daño (i-frames): una bandera y un temporizador que ignora el daño unos instantes, con parpadeo del sprite.
  • Knockback: aplicar un impulso al recibir daño (combina con Rigidbody).
  • Tipos de daño (fuego, hielo) y resistencias, ampliando RecibirDaño.

Errores frecuentes#

  • Poner la vida como public int que cualquiera modifica (usa métodos + propiedad de solo lectura).
  • Que cada enemigo tenga su propio código de vida distinto (unifica con el componente + interfaz).
  • Que Salud conozca la UI directamente (usa eventos).
  • No comprobar muerto y disparar Morir() varias veces (drops duplicados, doble game over).

Resumen#

Un componente Salud que implementa IDañable y expone eventos (AlCambiar, AlMorir). Cualquier fuente de daño golpea con TryGetComponent<IDañable>() sin conocer el objetivo, y la barra de vida, los efectos y el game over se suscriben a los eventos. Reutilizable, desacoplado y ampliable a i-frames, knockback y tipos de daño.

Fuentes y para profundizar