Menu
CoddyTech

Llega a la base

Lección 3 de 18 del curso Juego de Unity: defensa de torres de Coddy.

Un enemigo que llega al último punto de ruta ha alcanzado la base: el jugador pierde vidas y el enemigo desaparece. Las vidas pertenecen a GameManager, que las muestra en pantalla. El enemigo no debería necesitar una referencia a GameManager para informarlo: pronto se crearán docenas de enemigos a partir de un prefab, y un prefab no puede apuntar a un objeto de la escena.

Un evento estático resuelve ambos problemas. Pertenece a la clase Enemy, no a un enemigo concreto, así que GameManager se suscribe una sola vez y recibe las notificaciones de todos los enemigos, también de los que aparezcan más adelante. Cada enemigo lo invoca pasándose a sí mismo como argumento, para que el receptor pueda leer qué tipo de enemigo logró pasar. Una moneda en un juego de plataformas informa de la misma manera:

public class Coin : MonoBehaviour
{
    public static event Action<Coin> Collected;
    public int value = 1;

    void OnTriggerEnter(Collider other)
    {
        Collected?.Invoke(this);
        Destroy(gameObject);
    }
}
// ScoreBoard.cs
void OnEnable()
{
    Coin.Collected += AddCoin;
}

void OnDisable()
{
    Coin.Collected -= AddCoin;
}

void AddCoin(Coin coin)
{
    score += coin.value;
}

Un evento estático vive tanto como el juego, así que -= importa más que nunca: se seguiría llamando a un ScoreBoard destruido que no se hubiera desuscrito, y su código fallaría al intentar acceder al texto destruido. OnEnable y OnDisable van en pareja, así que a cada += le corresponde su -=.

challenge icon

Desafío

Fácil

La base necesita vidas, y cada enemigo que la alcance debe restarle vidas.

  1. En EnemyData, agrega un int público damage: las vidas que este tipo le resta a la base.
  2. En Enemy, declara un evento estático público ReachedBase que pase el enemigo (Action<Enemy>). Cuando el enemigo llegue al último punto de ruta, invoca el evento pasándose a sí mismo y destruye al enemigo, en lugar de detenerse allí.
  3. En GameManager, agrega un int serializado startLives (20) y un int privado lives que comience con ese valor. Suscríbete a Enemy.ReachedBase en OnEnable y cancela la suscripción en OnDisable. Cada enemigo que llegue resta de las vidas el valor de damage de su recurso.
  4. Muestra las vidas en un TMP_Text serializado livesText, como Lives: 20, al inicio y después de cada cambio.

El objeto Game tiene el GameManager, en el Inspector se asigna LivesText, y ambos recursos restan 1 vida. Pulsa Play, espera a que ambos enemigos lleguen a la base y luego pulsa Check.

Pruébalo tú mismo

using UnityEngine;

public class Enemy : MonoBehaviour
{
    public EnemyData data;
    public Transform[] waypoints;

    private int next = 1;
    private int health;

    void Awake()
    {
        health = data.maxHealth;
    }

    void Update()
    {
        if (next >= waypoints.Length)
        {
            return;
        }

        Vector3 target = waypoints[next].position;
        transform.position = Vector3.MoveTowards(transform.position, target, data.speed * Time.deltaTime);
        if (transform.position == target)
        {
            next++;
        }
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Juego de Unity: defensa de torres