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.
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.csprzechowuj zapasowe ślady stóp wQueue<GameObject>. Poletrailkaż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 polifesekundach wraca przeztrail.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
}
}
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
1Komponenty, nie hierarchie
Małe komponentyPodstawowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPodsumowanie: modułowa wieżyczka4Dane serializowane
Klasy serializowalneListy w InspectorzeWyliczenia w InspectorzePodsumowanie: tabela łupów10Projekt: Arena przetrwania
BohaterTypy wrogów2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPodsumowanie: klawisz interakcji5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaFale jako danePowtórka: baza danych przedmiotów8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearest3Zdarzenia
Zdarzenia C# w UnitySubskrypcja w OnEnablePola UnityEventZdarzenia sterują interfejsemPodsumowanie: wyskakujące okno osiągnięcia6Zapisywanie za pomocą JSON
JsonUtilityZapisz gręWczytywanie i wartości domyślnePowtórka: sloty zapisu9Pooling obiektów
Dlaczego używać poolingu obiektówPool z kolejkąObjectPool w UnityPodsumowanie: pula pocisków