Menu
CoddyTech

Subskrypcja w OnEnable

Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 11 z 50.

Słuchacz, który zostanie zniszczony, sam nie opuszcza zdarzenia. Zdarzenie nadal przechowuje jego metodę, a następne wywołanie Invoke wywołuje ją na zniszczonym komponencie. Pierwsze użycie transform w tej metodzie powoduje wyjątek MissingReferenceException, a ponieważ wyjątek kończy Invoke, pomijani są również kolejni słuchacze. Dlatego każdemu += musi odpowiadać -=, a para metod Unity do tego celu to OnEnable i 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 wywołuje OnDisable, gdy obiekt zostanie wyłączony za pomocą SetActive(false), gdy skrypt zostanie wyłączony oraz gdy obiekt zostanie zniszczony, przed OnDestroy. OnEnable jest uruchamiane za każdym razem, gdy obiekt zostaje ponownie włączony. Dzięki tej parze strażnik nasłuchuje dokładnie wtedy, gdy jest aktywny: zniszczony strażnik znika ze zdarzenia, strażnik wyłączony na potrzeby przerywnika filmowego ignoruje alarm, a po ponownym włączeniu znów nasłuchuje.

Dwie inne kombinacje nie działają poprawnie. Gdy += znajduje się w Start, a -= w OnDisable, strażnik wyłączony i ponownie włączony już nie nasłuchuje, ponieważ Start jest uruchamiane tylko raz. Gdy += znajduje się w OnEnable, a brakuje -=, każde ponowne włączenie dodaje RunTo jeszcze raz, więc jedno wywołanie alarmu uruchamia ją dwukrotnie. Usunięcie metody, która nie jest subskrybowana, nic nie robi, więc w OnDisable nigdy nie trzeba sprawdzać, czy wykonać -=.

challenge icon

Wyzwanie

Łatwy

Dzwon w wiosce dzwoni za każdym razem, gdy naciskasz Spację (Bell.cs, gotowe), a jego zdarzenie OnRing informuje mieszkańców wioski. Mieszkaniec podskakuje przy każdym dzwonku i wraca do domu po ringsToLeave dzwonkach: Hop go niszczy. Ana wraca do domu po 2 dzwonkach. Zadzwoń po raz trzeci, a w konsoli pojawi się MissingReferenceException.

Napraw Villager.cs, aby mieszkaniec nasłuchiwał dzwonka dokładnie wtedy, gdy jest aktywny:

  • Za każdym razem, gdy mieszkaniec zostaje włączony, zasubskrybuj zdarzenie dzwonka metodą Hop, a gdy mieszkaniec zostaje wyłączony lub zniszczony — anuluj subskrypcję. Pozostaw Hop i Update bez zmian.
  • Mieszkaniec wyłączony za pomocą SetActive(false) nie podskakuje. Po ponownym włączeniu podskakuje raz przy każdym dzwonku.

Naciśnij Play, zadzwoń cztery razy i obserwuj konsolę, a następnie naciśnij Check.

Spróbuj swoich sił

using UnityEngine;

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

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

    void Update()
    {
        // opadnij z powrotem na ziemię po podskoku
        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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Architektura gier w Unity