Menu
CoddyTech

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.

challenge icon

Aufgabe

Mittel

Verwende einen Pool für die Fußspuren, statt sie zu zerstören.

  1. Bewahre in Trail übrige Objekte in einer Queue<GameObject> auf. Return(footprint) deaktiviert das Objekt und fügt es der Warteschlange hinzu; Start erstellt prewarm Fußspuren und gibt sie zurück.
  2. Get(position) nimmt ein übriges Objekt aus der Warteschlange (oder erstellt eines), platziert es und aktiviert es.
  3. Ersetze in Footprint den Aufruf von Destroy: Setze das Alter in OnEnable zurück; nach life Sekunden wird trail.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

Übe selbstständig: Unity-Playground