Menu
CoddyTech

Suscribirse en OnEnable

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 13 de 64.

Un oyente que se destruye no abandona el evento por sí solo. El evento sigue conservando su método, y la siguiente llamada a Invoke lo ejecuta en el componente destruido. El primer uso de transform en ese método lanza MissingReferenceException y, como una excepción interrumpe Invoke, también se omiten los oyentes que vienen después. Así que cada += necesita un -=, y el par de métodos de Unity para ello es OnEnable y 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);
    }
}

Unity llama a OnDisable cuando el objeto se desactiva con SetActive(false), cuando se desactiva el script y cuando se destruye el objeto, antes de OnDestroy. OnEnable se ejecuta cada vez que vuelve a activarse. Con este par, un guardia escucha exactamente mientras está activo: un guardia destruido deja de estar en el evento, uno desactivado durante una cinemática ignora la alarma y, cuando se vuelve a activar, vuelve a escuchar.

Otras dos combinaciones dan problemas. Con += en Start y -= en OnDisable, un guardia que se desactiva y se vuelve a activar nunca vuelve a escuchar, porque Start solo se ejecuta una vez. Con += en OnEnable y sin -=, cada vez que se reactiva se añade RunTo de nuevo, y una alarma lo llama dos veces. Quitar un método que no está suscrito no hace nada, así que OnDisable nunca necesita comprobar nada antes de usar -=.

challenge icon

Desafío

Fácil

Haz que cada aldeano escuche la campana solo mientras esté activa.

  1. En Villager.cs, mueve bell.OnRing += Hop; de Start() a un nuevo void OnEnable() y elimina Start().
  2. Añade void OnDisable() con bell.OnRing -= Hop;. «Comprobar» activa y desactiva a Cleo para probar esto.

Pulsa «Jugar» y haz sonar la campana cuatro veces: Ana se va a casa después del segundo toque y no aparece ningún error. Luego, pulsa «Comprobar».

Pruébalo tú mismo

using UnityEngine;

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

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

    void Update()
    {
        // vuelve a caer al suelo después de un 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);
        }
    }
}

Todas las lecciones de Arquitectura de juegos en Unity

Practica por tu cuenta: Playground de Unity