Suscribirse en OnEnable
Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 11 de 50.
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 termina la llamada a Invoke, también se omiten los oyentes que vienen después. Por eso, cada += necesita un -=, y el par de métodos de Unity para eso 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, un guardia desactivado durante una cinemática ignora la alarma y, cuando vuelve a activarse, escucha de nuevo.
Otras dos combinaciones dan problemas. Con += en Start y -= en OnDisable, un guardia que se desactiva y vuelve a activarse nunca vuelve a escuchar, porque Start se ejecuta una sola vez. Con += en OnEnable y sin -=, cada vez que vuelve a activarse se añade RunTo otra vez, y una alarma lo llama dos veces. Eliminar un método que no está suscrito no hace nada, así que nunca hace falta comprobarlo antes de usar -= en OnDisable.
Desafío
FácilLa campana del pueblo suena cada vez que pulsas la barra espaciadora (Bell.cs, listo), y su evento OnRing avisa a los aldeanos. Un aldeano da un salto con cada campanada y se va a casa después de ringsToLeave campanadas: Hop lo destruye. Ana se va a casa después de 2 campanadas. Toca la campana una tercera vez y la Consola muestra una MissingReferenceException.
Corrige Villager.cs para que un aldeano escuche la campana exactamente mientras está activo:
- Suscribe
Hopal evento de la campana cada vez que se activa el aldeano, y cancela la suscripción cuando se desactiva o se destruye. ManténHopyUpdatetal como están. - Un aldeano desactivado con
SetActive(false)no da saltos. Al volver a activarlo, da un salto por cada campanada.
Pulsa Play, toca la campana cuatro veces y observa la Consola; después, pulsa Check.
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);
}
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Arquitectura de juegos en Unity
1Componentes, no jerarquías
Componentes pequeñosUn script base para enemigosComponentes abstractosComponentes que trabajan juntosRepaso: torreta modular4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botín7Máquinas de estados
Estados como clasesUna máquina de estadosTransicionesCerebros de enemigosRepaso: estados de puertas10Proyecto: Superviviente de la arena
El héroeTipos de enemigos2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: tecla de interacción5ScriptableObjects
Recursos de datosEstadísticas de armasConfiguración compartidaOleadas como datosRepaso: base de datos de objetos