Menu
CoddyTech

הרשמה ב-OnEnable

חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 13 מתוך 64.

מאזין שנהרס אינו יוצא מהאירוע מעצמו. האירוע עדיין מחזיק את המתודה שלו, והקריאה הבאה ל־Invoke מפעילה אותה ברכיב שנהרס. השימוש הראשון ב־transform במתודה זו זורק MissingReferenceException, ומכיוון שחריגה מסיימת את Invoke, גם המאזינים שאחריה מדולגים. לכן לכל += צריך להיות -=, וצמד המתודות של Unity לכך הוא OnEnable ו־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 קוראת ל־OnDisable כשהאובייקט מושבת באמצעות SetActive(false), כשהסקריפט מושבת וכשהאובייקט נהרס, לפני OnDestroy. ‏OnEnable מופעלת בכל פעם שהאובייקט חוזר לפעול. בעזרת הצמד הזה, שומר מאזין בדיוק כל עוד הוא פעיל: שומר שנהרס מוסר מהאירוע, שומר שהושבת עבור קטע מעבר מתעלם מהאזעקה, וברגע שהוא מופעל שוב הוא מאזין שוב.

שני צימודים אחרים גורמים לבעיות. עם += ב־Start ו־-= ב־OnDisable, שומר שהושבת והופעל מחדש לעולם לא יאזין שוב, כי Start מופעלת רק פעם אחת. עם += ב־OnEnable וללא -=, כל חזרה מוסיפה שוב את RunTo, ואז אזעקה אחת קוראת לה פעמיים. הסרה של מתודה שאינה רשומה לא עושה דבר, ולכן לעולם אין צורך בבדיקה לפני -= ב־OnDisable.

challenge icon

אתגר

קל

יש לגרום לכל תושב להאזין לפעמון רק כשהוא פעיל.

  1. ב־Villager.cs, העבירו את bell.OnRing += Hop; מ־Start() אל void OnEnable() חדש, ומחקו את Start().
  2. הוסיפו void OnDisable() עם bell.OnRing -= Hop;. בלחיצה על „בדיקה” מכבים ומפעילים את Cleo כדי לבדוק זאת.

לחצו על „שחק” והפעילו את הפעמון ארבע פעמים: Ana חוזרת הביתה אחרי הצלצול השני, ולא מופיעה שגיאה. לאחר מכן לחצו על „בדיקה”.

נסו בעצמכם

using UnityEngine;

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

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

    void Update()
    {
        // ליפול בחזרה לקרקע אחרי קפיצה
        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);
        }
    }
}

כל השיעורים ביחידה ארכיטקטורת משחקים ב-Unity

תרגלו בעצמכם: Unity אונליין