Menu
CoddyTech
flag Ar iconالعربيةdown icon

الاشتراك في 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.

challenge icon

التحدي

سهل

يرن جرس القرية في كل مرة تضغط فيها على مفتاح المسافة (Bell.cs، جاهز)، ويُعلم حدثه OnRing أهل القرية. يقفز أحد أهل القرية مع كل رنين ويعود إلى المنزل بعد ringsToLeave رنينات: إذ تدمره Hop. تعود آنا إلى المنزل بعد رنينتين. دق الجرس مرة ثالثة وستظهر في وحدة التحكم رسالة 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);
        }
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس هندسة الألعاب في Unity