Menu
CoddyTech

In OnEnable abonnieren

Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 13 von 64.

Ein zerstörter Listener verlässt das Ereignis nicht von selbst. Das Ereignis hält seine Methode weiterhin fest, und beim nächsten Aufruf ruft Invoke sie auf der zerstörten Komponente auf. Die erste Verwendung von transform in dieser Methode löst eine MissingReferenceException aus, und da eine Ausnahme den Invoke beendet, werden auch die Listener danach übersprungen. Daher braucht jedes += ein -=, und Unitys Methodenpaar dafür ist OnEnable und 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 ruft OnDisable auf, wenn das Objekt mit SetActive(false) ausgeschaltet wird, wenn das Skript deaktiviert wird und wenn das Objekt zerstört wird – vor OnDestroy. OnEnable wird jedes Mal ausgeführt, wenn es wieder eingeschaltet wird. Mit diesem Methodenpaar hört ein Wächter genau dann zu, wenn er aktiv ist: Ein zerstörter Wächter ist aus dem Ereignis entfernt, ein für eine Zwischensequenz ausgeschalteter Wächter ignoriert den Alarm, und sobald er wieder eingeschaltet wird, hört er wieder zu.

Zwei andere Kombinationen funktionieren nicht richtig. Mit += in Start und -= in OnDisable hört ein aus- und wieder eingeschalteter Wächter nie wieder zu, weil Start nur einmal ausgeführt wird. Mit += in OnEnable und ohne -= fügt jede Rückkehr RunTo erneut hinzu, und ein Alarm ruft die Methode zweimal auf. Das Entfernen einer Methode, die nicht abonniert ist, bewirkt nichts; daher ist bei -= in OnDisable nie eine Prüfung nötig.

challenge icon

Aufgabe

Einfach

Lass jeden Dorfbewohner nur dann auf die Glocke hören, wenn er aktiv ist.

  1. Verschiebe in Villager.cs bell.OnRing += Hop; aus Start() in eine neue Methode void OnEnable() und lösche Start().
  2. Füge void OnDisable() mit bell.OnRing -= Hop; hinzu. „Prüfen“ schaltet Cleo aus und wieder ein, um dies zu testen.

Drücke auf „Spielen“ und läute viermal: Ana geht nach dem zweiten Läuten nach Hause, und es wird kein Fehler angezeigt. Drücke dann auf „Prüfen“.

Probier es selbst

using UnityEngine;

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

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

    void Update()
    {
        // nach einem Sprung wieder zu Boden fallen
        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);
        }
    }
}

Alle Lektionen in Spielarchitektur in Unity

Übe selbstständig: Unity-Playground