Menu
CoddyTech

Chegue à base

Lição 3 de 18 do curso Jogo de Unity: Defesa de Torres da Coddy.

Um inimigo que chega ao último ponto de passagem alcançou a base: o jogador perde vidas e o inimigo desaparece. As vidas pertencem ao GameManager, que as exibe na tela. O inimigo não deveria precisar de uma referência ao GameManager para informar isso: em breve, os inimigos serão criados às dúzias a partir de um prefab, e um prefab não pode apontar para um objeto na cena.

Um evento estático resolve os dois problemas. Ele pertence à classe Enemy, não a um único inimigo, então o GameManager se inscreve uma vez e recebe notificações de todos os inimigos, inclusive dos que forem instanciados mais tarde. Cada inimigo o aciona passando a si mesmo como argumento, para que o ouvinte possa ler que tipo de inimigo conseguiu passar. Uma moeda em um jogo de plataforma informa da mesma maneira:

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;
}

Um evento estático existe enquanto o jogo estiver em execução, então o -= é mais importante do que nunca: um ScoreBoard destruído que nunca se desinscreveu ainda seria chamado, e seu código falharia ao acessar o texto destruído. OnEnable e OnDisable vêm em pares, então cada += recebe seu -=.

challenge icon

Desafio

Fácil

A base precisa de vidas, e um inimigo que a alcance deve fazer com que elas diminuam.

  1. Em EnemyData, adicione um public int damage: a quantidade de vidas que esse tipo de inimigo tira da base.
  2. Em Enemy, declare um evento estático público ReachedBase que passe o inimigo (Action<Enemy>). Quando o inimigo chegar ao último waypoint, dispare o evento passando o próprio inimigo e destrua-o, em vez de fazê-lo parar ali.
  3. Em GameManager, adicione um int serializado startLives (20) e um int privado lives que comece com esse valor. Inscreva-se em Enemy.ReachedBase em OnEnable e cancele a inscrição em OnDisable. Cada inimigo que passar reduz das vidas o valor de damage do asset dele.
  4. Mostre as vidas em um TMP_Text serializado livesText, como Lives: 20, no início e após cada alteração.

O objeto Game tem o GameManager, o Inspector vincula o LivesText, e ambos os assets tiram 1 vida. Pressione Play, espere os dois inimigos chegarem à base e, em seguida, Check.

Experimente você mesmo

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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Jogo de Unity: Defesa de Torres