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;. يوقف «تحقق» كليو ويعيد تشغيلها لاختبار ذلك.

اضغط على «العب» وقرع الجرس أربع مرات: تعود آنا إلى منزلها بعد القرعة الثانية، ولا يظهر أي خطأ. ثم اضغط على «تحقق».

جرّب بنفسك

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

تدرّب بنفسك: Playground لـ Unity