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 -=.
Desafío
FácilHaz que cada aldeano escuche la campana solo mientras esté activa.
- En
Villager.cs, muevebell.OnRing += Hop;deStart()a un nuevovoid OnEnable()y eliminaStart(). - Añade
void OnDisable()conbell.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
1Componentes, no jerarquías
Componentes pequeñosUn script base para enemigosComponentes abstractosComponentes que trabajan juntosRepaso: torreta modularRepaso: cañón doble4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botínRepaso: sortear el botín2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: Tecla de interacciónRepaso: El más cercano al alcance5ScriptableObjects
Activos de datosEstadísticas de armasConfiguración compartidaGuardar el vientoOleadas como datosRepaso: base de datos de objetosRepaso: comprar en la tienda3Eventos
Eventos de C# en UnitySuscribirse en OnEnableCampos UnityEventLos eventos controlan la interfazRepaso: ventana emergente de logrosRepaso: temporizador de la ventana emergentePractica por tu cuenta: Playground de Unity