הירשם ב-OnEnable
חלק מהיחידה ארכיטקטורת משחקים ב-Unity במסלול ה-Unity של Coddy. שיעור 11 מתוך 50.
מאזין שהושמד לא עוזב את האירוע בעצמו. האירוע עדיין מחזיק את המתודה שלו, והקריאה הבאה ל-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.
אתגר
קלהפעמון בכפר מצלצל בכל פעם שלוחצים על Space (Bell.cs, מוכן), והאירוע שלו OnRing מודיע לתושבי הכפר. תושב הכפר מנתר בכל צלצול והולך הביתה אחרי ringsToLeave צלצולים: Hop משמיד אותו. אנה הולכת הביתה אחרי 2 צלצולים. צלצלו פעם שלישית, והמסוף יציג MissingReferenceException.
תקנו את Villager.cs כך שתושב הכפר יאזין לפעמון בדיוק כל עוד הוא פעיל:
- רשמו את
Hopלאירוע של הפעמון בכל פעם שתושב הכפר מופעל, והסירו את הרישום שלו כשהתושב מושבת או מושמד. השאירו אתHopואתUpdateכפי שהם. - תושב כפר שמושבת באמצעות
SetActive(false)לא מנתר. כשמפעילים אותו שוב, הוא מנתר פעם אחת בכל צלצול.
לחצו על Play, צלצלו בפעמון ארבע פעמים וצפו במסוף, ואז לחצו על Check.
נסו בעצמכם
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
1רכיבים, לא היררכיות
רכיבים קטניםסקריפט בסיס לאויברכיבים מופשטיםרכיבים שעובדים יחדסיכום: צריח מודולרי3אירועים
אירועי C# ב-Unityהירשם ב-OnEnableשדות UnityEventאירועים מניעים את ממשק המשתמשסיכום: חלונית הישג