Programación de Daño en Videojuegos: Lógica de Armas y Magia

Clase 23 de 33Curso de VR con Unity

Resumen

Un sistema de daño sólido en Unity con C# requiere reglas claras: quién hace daño, a quién y cuánto, sin golpes a aliados ni a uno mismo. Aquí verás cómo organizarlo con enumerados, triggers y configuración de armas y magia, manteniendo un buen balance entre velocidad de ataque y daño.

¿Cómo estructurar el sistema de daño con enumerados?

Para diferenciar el daño del personaje y el del enemigo se usa un enumerado. DamageType permite separar lógicas y evitar daño entre entidades del mismo tipo. Además, tanto el script de vida como el de daño llevan una variable pública para indicar su tipo por defecto.

  • DamageType define Player y Enemy.
  • Health incluye el tipo de vida para saber a quién representa.
  • Damage incluye el tipo de daño y la cantidad base (por ejemplo, 10).

Código base:

// Enumerado global
public enum DamageType { Player, Enemy }

// En Health
public DamageType type = DamageType.Enemy; // Configurable a Player en el Inspector.

// En Damage
public DamageType type = DamageType.Enemy; // Configurable a Player en armas y proyectiles.
public float damage = 10f;                 // Daño base por defecto.

¿Por qué usar la variable type en health y damage?

  • Evita fuego amigo: si un enemigo choca con otro, no se dañan.
  • Evita autodaño: el personaje no se hiere con su propia espada.
  • Escala a más facciones: solo hay que añadir valores al enumerado.

¿Cómo aplicar daño con triggers y colliders en C#?

El daño se ejecuta con triggers. Al entrar en un collider configurado como isTrigger, OnTriggerEnter pregunta si el otro objeto tiene vida y, solo si es de otro tipo, resta puntos de vida. Así, una bola de fuego daña al enemigo cuando entra en su collider.

  • Usa GetComponent() para validar si el objetivo tiene vida.
  • Compara tipos con DamageType para decidir si aplicar daño.
  • currentDamage permite ajustar el daño en tiempo real (por ejemplo, al usar escudo).

Ejemplo del flujo en el script de daño:

void OnTriggerEnter(Collider other)
{
    var targetHealth = other.GetComponent<Health>();
    if (targetHealth == null) return;            // Sin vida, no hay daño.

    if (targetHealth.type == this.type) return;  // Mismo tipo: no daña.

    float currentDamage = damage;                // Copia para poder modificar.

    var targetWeapons = other.GetComponent<Weapons>();
    if (targetWeapons != null && targetWeapons.shieldActive)
    {
        currentDamage /= 5f;                     // Escudo activo: reduce daño.
    }

    targetHealth.healthPoints -= currentDamage;  // Aplica daño.
}

¿Cómo evitar daño entre aliados o a uno mismo?

  • Compara targetHealth.type con this.type antes de restar vida.
  • Si son iguales: return y no se modifica la salud.

¿Cómo reducir el daño con escudo activo?

  • Comprueba GetComponent() y su bandera shieldActive.
  • Si está activo: divide currentDamage (por ejemplo, entre 5).
  • Permite estrategias de defensa sin desactivar por completo el ataque.

¿Qué configurar en player, armas y prefabs para balancear daño?

Una buena configuración diferencia qué objeto hace daño, cuál recibe y cómo se balancea el juego entre rapidez y potencia.

  • Player con vida.
  • Añade el script Health al personaje.
  • En type: selecciona Player.
  • Define puntos de vida, por ejemplo, 100.

  • Armas del personaje.

  • El daño lo hace el arma, no el personaje.
  • Añade el script Damage a la espada u otra arma.
  • En type: selecciona Player.
  • Activa el isTrigger del collider del arma para que funcione OnTriggerEnter.

  • Escudo del personaje.

  • No necesita script de daño.
  • Puede no tener vida propia si no se requiere.
  • La reducción de daño se controla con shieldActive en el controlador de armas.

  • Proyectil de magia (bola de fuego) en prefab.

  • Abre el prefab con Rigidbody, SphereCollider y AudioSource.
  • Añade el script Damage y configúralo como Player.
  • Ajusta daño alto (por ejemplo, 100) para compensar su cadencia: una bala cada dos segundos.

  • Balance velocidad vs daño.

  • Espada: daño bajo (10) pero ataques rápidos.
  • Bola de fuego: daño alto (100) pero disparo lento.
  • Evita que la rapidez destruya enemigos demasiado rápido sin apuntar ni planear.

¿Te gustaría compartir tu implementación de DamageType, OnTriggerEnter o el ajuste del escudo? Comenta tus dudas y mejoras.