Menu
CoddyTech

Pool z kolejką

Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 47 z 64.

Basen potrzebuje miejsca do przechowywania zapasowych obiektów, a C# ma do tego kolekcję Queue<T>: Enqueue dodaje element na końcu, Dequeue pobiera element z początku, a Count podaje, ile elementów czeka. W tym akwarium co 0.3 sekundy wypływa bańka, a każda z nich wraca do puli przy powierzchni:

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, na prefabie bąbelka
public BubblePool pool;

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

Get najpierw sprawdza Count, ponieważ wywołanie Dequeue na pustej kolejce powoduje wyjątek InvalidOperationException. Dopiero potem wywołuje Instantiate, a pole pool trzeba ustawić tylko nowej bańce: używana ponownie nadal je ma. Kolejka wydaje bańkę, która czekała najdłużej — pierwsza weszła, pierwsza wychodzi. Bańka przy powierzchni wywołuje Return zamiast Destroy i pozostaje w scenie, nieaktywna, aż do następnego wywołania Get.

Get ustawia pozycję bańki przed wywołaniem SetActive(true), ponieważ jej włączenie natychmiast uruchamia OnEnable, a wszystko, co się tam dzieje, powinno widzieć nową pozycję, a nie tę, w której bańka ostatnio zniknęła. Właśnie wtedy używany ponownie obiekt zaczyna od początku: Awake i Start uruchomiły się raz, gdy utworzono bańkę, a OnEnable uruchamia się przy każdym wywołaniu Get.

challenge icon

Wyzwanie

Średni

Umieszczaj odciski w puli zamiast ich niszczyć.

  1. W Trail przechowuj zapasowe obiekty w Queue<GameObject>. Return(footprint) wyłącza obiekt i dodaje go do kolejki; Start tworzy prewarm odcisków i zwraca je.
  2. Get(position) pobiera zapasowy obiekt z kolejki (lub tworzy nowy), umieszcza go i włącza.
  3. W Footprint zastąp wywołanie Destroy: zresetuj wiek w OnEnable; po life sekundach wywołaj trail.Return(gameObject).

Naciśnij „Graj” i idź: odciski znikną po 1.5 sekundy. Następnie naciśnij „Sprawdź”.

Spróbuj swoich sił

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;
        // Wypełnij pulę śladami stóp przygotowanymi z wyprzedzeniem
    }

    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)
    {
        // Zapasowe ślady stóp czekają w puli
    }
}

Wszystkie lekcje w sekcji Architektura gier w Unity

Poćwicz samodzielnie: Edytor online Unity