الاشتراك في 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 إلى التحقق مطلقًا.
التحدي
سهلاجعل كل قروي يستمع إلى الجرس فقط أثناء نشاطه.
- في
Villager.cs، انقلbell.OnRing += Hop;منStart()إلىvoid OnEnable()جديد، واحذفStart(). - أضف
void OnDisable()معbell.OnRing -= Hop;. يوقف «تحقق» كليو ويعيد تشغيلها لاختبار ذلك.
اضغط على «العب» وقرع الجرس أربع مرات: تعود آنا إلى منزلها بعد القرعة الثانية، ولا يظهر أي خطأ. ثم اضغط على «تحقق».
جرّب بنفسك
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المكوّنات، لا التسلسلات الهرمية
مكوّنات صغيرةنص برمجي أساسي للعدومكوّنات مجرّدةالمكوّنات تعمل معًامراجعة: برج معياريمراجعة: مدفع مزدوج4البيانات المُسلسلة
الأصناف القابلة للتسلسلالقوائم في Inspectorالتعدادات في Inspectorمراجعة: جدول الغنائممراجعة: اختيار الغنائم عشوائيًا2الواجهات في Unity
IDamageableالواجهات وTryGetComponentGetComponentsمراجعة: مفتاح التفاعلمراجعة: أقرب عنصر ضمن النطاقتدرّب بنفسك: Playground لـ Unity