Menu
CoddyTech

Inscreva-se em OnEnable

Parte da seção Arquitetura de jogos no Unity do Journey de Unity da Coddy. Lição 11 de 50.

Um listener que é destruído não sai do evento por conta própria. O evento ainda mantém seu método, e a próxima chamada de Invoke o chama no componente destruído. O primeiro uso de transform nesse método lança MissingReferenceException e, como uma exceção encerra o Invoke, os listeners posteriores também são ignorados. Portanto, cada += precisa de um -=, e o par de métodos do Unity para isso é OnEnable e OnDisable:

public class Guard : MonoBehaviour
{
    public Alarm alarm;

    void OnEnable()
    {
        alarm.OnTriggered += RunTo;
    }

    void OnDisable()
    {
        alarm.OnTriggered -= RunTo;
    }

    void RunTo(Vector3 spot)
    {
        transform.LookAt(spot);
    }
}

O Unity chama OnDisable quando o objeto é desativado com SetActive(false), quando o script é desativado e quando o objeto é destruído, antes de OnDestroy. OnEnable é executado cada vez que ele é reativado. Com esse par, um guarda escuta exatamente enquanto está ativo: um guarda destruído deixa de fazer parte do evento, um guarda desativado para uma cena cinemática ignora o alarme e, quando é reativado, volta a escutar.

Outros dois pareamentos dão errado. Com += em Start e -= em OnDisable, um guarda desativado e reativado nunca volta a escutar, porque Start é executado apenas uma vez. Com += em OnEnable e sem -=, cada reativação adiciona RunTo novamente, e um alarme o chama duas vezes. Remover um método que não está inscrito não faz nada, então -= em OnDisable nunca precisa de uma verificação.

challenge icon

Desafio

Fácil

O sino da vila toca cada vez que você pressiona a barra de espaço (Bell.cs, pronto), e seu evento OnRing avisa os aldeões. Um aldeão dá um salto a cada toque e vai para casa depois de ringsToLeave toques: Hop o destrói. Ana vai para casa depois de 2 toques. Toque mais uma vez e o Console exibirá uma MissingReferenceException.

Corrija Villager.cs para que um aldeão escute o sino exatamente enquanto estiver ativo:

  • Inscreva Hop no evento do sino sempre que o aldeão for ativado e cancele a inscrição quando ele for desativado ou destruído. Mantenha Hop e Update como estão.
  • Um aldeão desativado com SetActive(false) não dá saltos. Quando for ativado novamente, ele dá um salto por toque.

Pressione Play, toque o sino quatro vezes e observe o Console; em seguida, clique em Check.

Experimente você mesmo

using UnityEngine;

public class Villager : MonoBehaviour
{
    public Bell bell;
    public int ringsToLeave = 3;
    public int hops;

    void Start()
    {
        bell.OnRing += Hop;
    }

    void Update()
    {
        // volta ao chão após um salto
        Vector3 p = transform.position;
        transform.position = new Vector3(p.x, Mathf.MoveTowards(p.y, 0.5f, 4f * Time.deltaTime), p.z);
    }

    void Hop(int ring)
    {
        hops++;
        transform.position += Vector3.up * 0.8f;
        if (hops == ringsToLeave)
        {
            Debug.Log(name + " goes home");
            Destroy(gameObject);
        }
    }
}
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 Arquitetura de jogos no Unity