Menu
CoddyTech

Pool z kolejką

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

Basen potrzebuje miejsca, w którym będzie przechowywać zapasowe obiekty, a C# ma do tego kolekcję Queue<T>: Enqueue dodaje element na końcu, Dequeue pobiera element z początku, a Count podaje liczbę oczekujących elementów. W tym akwarium co 0.3 sekundy wypływa bańka, a każda bańka 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 zgłasza wyjątek InvalidOperationException. Dopiero wtedy wywołuje Instantiate, a pole pool trzeba ustawić tylko dla nowej bańki: ponownie używana już je ma. Kolejka wydaje najpierw 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 Get.

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

challenge icon

Wyzwanie

Średni

Ślady stóp na piasku. Strzałkami poruszasz graczem (gotowe). Trail.cs, umieszczony na graczu, tworzy ślad stopy co każde przebyte 1 jednostkę, wywołując Get(position), a każdy Footprint istnieje przez life (1.5) sekundy. Obecnie Get tworzy za każdym razem nowy ślad stopy, a każdy z nich sam się niszczy. Użyj puli:

  • W Trail.cs przechowuj zapasowe ślady stóp w Queue<GameObject>. Pole trail każdego śladu stopy utworzonego przez Trail musi wskazywać na ten obiekt Trail.
  • W Start wypełnij pulę liczbą śladów stóp równą prewarm (6); utwórz je i wyłącz, aby pierwsze kroki nie tworzyły niczego nowego.
  • Get(position) pobiera ślad stopy z kolejki, jeśli coś w niej jest, i tworzy nowy tylko wtedy, gdy kolejka jest pusta; następnie ustawia pozycję śladu stopy i go włącza.
  • Return(footprint) wyłącza ślad stopy i umieszcza go w kolejce.
  • W Footprint.cs ślad stopy śledzi swój wiek i po life sekundach wraca przez trail.Return(gameObject), zamiast zostać zniszczony. Ponownie użyty ślad stopy znów istnieje przez pełne 1.5 sekundy.

Naciśnij Play, pochodź przez chwilę, a następnie naciśnij Check.

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 wcześniej
    }

    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
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Architektura gier w Unity