Ein Pool mit einer Warteschlange
Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 47 von 64.
Ein Pool braucht einen Ort, an dem er seine übrigen Objekte aufbewahren kann, und C# bietet dafür die Sammlung Queue<T>: Enqueue fügt hinten ein Element hinzu, Dequeue nimmt das vorderste Element heraus, und Count gibt an, wie viele warten. In diesem Aquarium steigt alle 0.3 Sekunden eine Blase auf, und jede Blase kehrt an der Wasseroberfläche zum Pool zurück:
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, auf dem Blasen-Prefab
public BubblePool pool;
void Update()
{
transform.Translate(0f, 2f * Time.deltaTime, 0f);
if (transform.position.y > 5f) pool.Return(gameObject);
}Get prüft zuerst Count, denn Dequeue löst bei einer leeren Warteschlange eine InvalidOperationException aus. Erst danach wird Instantiate aufgerufen, und nur bei einer neuen Blase muss ihr Feld pool gesetzt werden: Eine wiederverwendete Blase hat es noch. Die Warteschlange gibt zuerst die Blase aus, die am längsten gewartet hat – nach dem Prinzip „First in, first out“. Eine Blase an der Wasseroberfläche ruft Return statt Destroy auf und bleibt in der Szene inaktiv, bis das nächste Get aufgerufen wird.
Get positioniert die Blase vor SetActive(true), denn beim Aktivieren wird OnEnable sofort ausgeführt, und alles, was dort geschieht, sollte die neue Position sehen und nicht die Stelle, an der die Blase zuletzt verschwunden ist. Dort beginnt auch ein wiederverwendetes Objekt von vorn: Awake und Start wurden einmal ausgeführt, als die Blase erstellt wurde, und OnEnable wird bei jedem Get ausgeführt.
Aufgabe
MittelVerwende einen Pool für die Fußspuren, statt sie zu zerstören.
- Bewahre in
Trailübrige Objekte in einerQueue<GameObject>auf.Return(footprint)deaktiviert das Objekt und fügt es der Warteschlange hinzu;StarterstelltprewarmFußspuren und gibt sie zurück. Get(position)nimmt ein übriges Objekt aus der Warteschlange (oder erstellt eines), platziert es und aktiviert es.- Ersetze in
Footprintden Aufruf von Destroy: Setze das Alter inOnEnablezurück; nachlifeSekunden wirdtrail.Return(gameObject)aufgerufen.
Drücke „Spielen“ und gehe umher: Die Fußspuren verblassen nach 1.5 Sekunden. Drücke anschließend „Prüfen“.
Probier es selbst
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;
// Fülle den Pool mit vorab erzeugten Fußabdrücken
}
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)
{
// Ungenutzte Fußabdrücke warten im Pool
}
}
Alle Lektionen in Spielarchitektur in Unity
1Komponenten statt Hierarchien
Kleine KomponentenEin Basis-GegnerskriptAbstrakte KomponentenZusammenwirkende KomponentenRückblick: Modulares GeschützRückblick: Zwillingskanone4Serialisierte Daten
Serialisierbare KlassenListen im InspectorEnums im InspectorRückblick: Loot-TabelleRückblick: Beute auswürfeln2Schnittstellen in Unity
IDamageableSchnittstellen und TryGetComponentGetComponentsZusammenfassung: InteraktionstasteZusammenfassung: Nächstes in Reichweite5ScriptableObjects
Daten-AssetsWaffenwerteGemeinsame EinstellungenDen Wind speichernWellen als DatenRückblick: Item-DatenbankRückblick: Im Shop einkaufen8Wiederverwendbarer Code
ErweiterungsmethodenEin generisches SingletonGenerische HilfsmethodenRückblick: FindNearest3Ereignisse
C#-Ereignisse in UnityIn OnEnable abonnierenUnityEvent-FelderEreignisse steuern die UIRückblick: Erfolgs-PopupRückblick: Popup-Timer6Speichern mit JSON
JsonUtilityDas Spiel speichernLaden und StandardwerteRückblick: SpeicherplätzeSpeicherplatz auswählen und löschen9Objekt-Pooling
Warum Objekte poolenEin Pool mit einer WarteschlangeUnitys ObjectPoolRückblick: Geschoss-PoolÜbe selbstständig: Unity-Playground