Menu
CoddyTech

مجموعة باستخدام طابور

جزء من قسم هندسة الألعاب في Unity في رحلة Unity على Coddy. الدرس 47 من 64.

يحتاج المسبح إلى مكان يحتفظ فيه بالأجسام الاحتياطية، ولدى C# المجموعة المناسبة لذلك، Queue<T>: يضيف Enqueue عنصرًا في الخلف، ويأخذ Dequeue العنصر الموجود في المقدمة، ويبيّن Count عدد العناصر المنتظرة. يرسل هذا الحوض الفقاعات إلى الأعلى كل 0.3 ثانية، وتعود كل فقاعة إلى المسبح عند السطح:

using System.Collections.Generic;
using UnityEngine;

public class BubblePool : MonoBehaviour
{
    public GameObject bubblePrefab;
    private Queue<GameObject> pool = new Queue<GameObject>();
    private float timer;

    void Update()
    {
        timer += Time.deltaTime;
        if (timer >= 0.3f)
        {
            timer = 0f;
            Get(new Vector3(Random.Range(-2f, 2f), 0f, 0f));
        }
    }

    public GameObject Get(Vector3 position)
    {
        GameObject bubble;
        if (pool.Count > 0)
        {
            bubble = pool.Dequeue();
        }
        else
        {
            bubble = Instantiate(bubblePrefab);
            bubble.GetComponent<Bubble>().pool = this;
        }
        bubble.transform.position = position;
        bubble.SetActive(true);
        return bubble;
    }

    public void Return(GameObject bubble)
    {
        bubble.SetActive(false);
        pool.Enqueue(bubble);
    }
}
// Bubble.cs، على الـ prefab الخاص بالفقاعة
public BubblePool pool;

void Update()
{
    transform.Translate(0f, 2f * Time.deltaTime, 0f);
    if (transform.position.y > 5f) pool.Return(gameObject);
}

يفحص Get قيمة Count أولًا، لأن استدعاء Dequeue على قائمة انتظار فارغة يؤدي إلى رمي استثناء InvalidOperationException. بعد ذلك فقط يستدعي Instantiate، والفقاعة الجديدة وحدها هي التي تحتاج إلى تعيين الحقل pool؛ أما الفقاعة المعاد استخدامها فالحقل معيّن فيها بالفعل. تمنح قائمة الانتظار أولًا الفقاعة التي انتظرت أطول مدة، أي ما يدخل أولًا يخرج أولًا. تستدعي الفقاعة عند السطح Return بدلًا من Destroy، وتبقى في المشهد، غير نشطة، إلى أن يحين استدعاء Get التالي.

يضع Get الفقاعة في موضعها قبل استدعاء SetActive(true)، لأن تفعيلها يشغّل OnEnable فورًا، وينبغي لأي شيء يحدث هناك أن يرى الموضع الجديد، لا الموضع الذي اختفت فيه آخر مرة. وهنا أيضًا يبدأ الجسم المعاد استخدامه من جديد: نُفّذ Awake وStart مرة واحدة عند إنشاء الفقاعة، بينما يُنفّذ OnEnable مع كل استدعاء لـ Get.

challenge icon

التحدي

متوسط

استخدم تجميع البصمات بدلًا من إتلافها.

  1. في Trail، احتفظ بنسخ احتياطية في Queue<GameObject>. تستبعد Return(footprint) البصمة من المشهد وتضيفها إلى قائمة الانتظار؛ وتنشئ Start عددًا من البصمات يساوي prewarm وتعيدها.
  2. تسحب Get(position) نسخة احتياطية من قائمة الانتظار (أو تنشئ واحدة)، وتضعها ثم تفعّلها.
  3. في Footprint، استبدل Destroy: أعد ضبط العمر في OnEnable؛ وبعد life ثانية، استدعِ trail.Return(gameObject).

اضغط «العب» وامشِ: ستختفي البصمات تدريجيًا بعد 1.5 ثانية. ثم اضغط «تحقق».

جرّب بنفسك

using System.Collections.Generic;
using UnityEngine;

public class Trail : MonoBehaviour
{
    public GameObject footprintPrefab;
    public float step = 1f;
    public int prewarm = 6;
    private Vector3 lastDrop;

    void Start()
    {
        lastDrop = transform.position;
        // املأ المجمّع بآثار الأقدام المُنشأة مسبقًا
    }

    void Update()
    {
        if (Vector3.Distance(transform.position, lastDrop) >= step)
        {
            lastDrop = transform.position;
            Get(new Vector3(transform.position.x, 0.02f, transform.position.z));
        }
    }

    public GameObject Get(Vector3 position)
    {
        GameObject footprint = Instantiate(footprintPrefab, position, Quaternion.identity);
        footprint.GetComponent<Footprint>().trail = this;
        return footprint;
    }

    public void Return(GameObject footprint)
    {
        // تنتظر آثار الأقدام الاحتياطية في المجمّع
    }
}

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

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