Menu
CoddyTech

A Pool with a Queue

Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 47 of 64.

A pool needs somewhere to keep its spare objects, and C# has the collection for it, Queue<T>: Enqueue adds an item at the back, Dequeue takes the one at the front, and Count says how many wait. This aquarium sends up a bubble every 0.3 seconds, and each bubble comes back to the pool at the surface:

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, on the bubble prefab
public BubblePool pool;

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

Get checks Count first, because Dequeue on an empty queue throws an InvalidOperationException. Only then does it Instantiate, and only a new bubble needs its pool field set: a reused one still has it. The queue hands out the bubble that has waited longest, first in, first out. A bubble at the surface calls Return instead of Destroy, and stays in the scene, inactive, until the next Get.

Get places the bubble before SetActive(true), because switching it on runs its OnEnable straight away, and anything there should see the new position, not where it last vanished. That is also where a reused object starts over: Awake and Start ran once, when the bubble was made, and OnEnable runs on every Get.

challenge icon

Challenge

Medium

Pool the footprints instead of destroying them.

  1. In Trail, keep spares in a Queue<GameObject>. Return(footprint) switches it off and enqueues it; Start makes prewarm footprints and returns them.
  2. Get(position) dequeues a spare (or makes one), places it and switches it on.
  3. In Footprint, replace the Destroy: reset the age in OnEnable; after life seconds, trail.Return(gameObject).

Press Play and walk: footprints fade after 1.5 seconds. Then Check.

Try it yourself

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;
        // Fill the pool with prewarm footprints
    }

    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)
    {
        // Spare footprints wait in the pool
    }
}

All lessons in Game Architecture in Unity

Practice on your own: Unity playground