Creation Wasteland Logo

Unity Development: Queues Are Not All Bad! (Part 3)

Category: Game Development

Published on 4/3/2025
By creationwasteland

SHARE:

In Part 1 we covered List<T> vs. LinkedList<T>, and in Part 2 we explored the LIFO power of Stack<T>. In this Part 3, we’ll turn our attention to Queues—the go-to FIFO (First-In-First-Out) collection for processing events, messages, and spawn orders in the order they arrive.

Understanding Queues in Unity

What is a Queue?

A Queue<T> is a dynamic, FIFO data structure. You add items to the “back” of the queue and remove them from the “front.” Its core operations are:

  1. Enqueue(T item): Add an item to the end.
  2. Dequeue(): Remove and return the item at the front.
  3. Peek(): Inspect the front item without removing it.

Internally, .NET’s Queue<T> uses a circular buffer (array) that doubles in size when full, giving O(1) amortized Enqueue/Dequeue performance.

When to Use Queues in Unity

Queues excel wherever you need guaranteed ordering of processing:

  • Spawn & Respawn Systems: Enqueue spawn requests so enemies or items appear in the exact order they were triggered.
  • Event Processing: Handle player inputs, UI events, or game-world triggers in the sequence they occur.
  • Pathfinding & BFS Traversals: Explore grid or graph neighbors in breadth-first order for shortest-path searches.
  • Networking & Messaging: Buffer incoming/outgoing packets to maintain smooth, ordered delivery.

Example: Enemy Spawn Queue

Here’s a simple spawn manager that enqueues pending enemy spawn requests and processes them at a fixed rate:

// SpawnRequest.cs
public struct SpawnRequest {
  public GameObject prefab;
  public Vector3 position;
  public Quaternion rotation;
}

// SpawnManager.cs
using System.Collections.Generic;
using UnityEngine;

public class SpawnManager : MonoBehaviour {
  public float spawnInterval = 1.0f;
  private float timer = 0f;
  private Queue<SpawnRequest> spawnQueue = new Queue<SpawnRequest>();

  void Update() {
    timer += Time.deltaTime;
    if (timer >= spawnInterval && spawnQueue.Count > 0) {
      var req = spawnQueue.Dequeue();
      Instantiate(req.prefab, req.position, req.rotation);
      timer = 0f;
    }
  }

  public void RequestSpawn(GameObject prefab, Vector3 pos, Quaternion rot) {
    var req = new SpawnRequest { prefab = prefab, position = pos, rotation = rot };
    spawnQueue.Enqueue(req);
  }

  public int PendingSpawns => spawnQueue.Count;
}
  

Analyzing the Example and Performance Considerations

Key Takeaways

  1. Strict FIFO Order: Ensures spawn requests fire in the order they were made.
  2. Constant-Time Operations: Enqueue, Dequeue, and Peek are O(1) amortized.
  3. Controlled Throughput: Processing one spawn per interval avoids performance spikes.

Queue vs. Other Collections

Queue Advantages:

  • Guaranteed processing order.
  • Lightweight buffer for bursty events or spikes.
  • Simplifies breadth-first algorithms and sequential workflows.

List / LinkedList Advantages:

  • List<T> offers random access and easy iteration.
  • LinkedList<T> allows O(1) insert/remove anywhere when you have a node reference.
  • Neither enforces strict FIFO discipline automatically.

Conclusion: Choosing the Right Structure

Whenever you need to process things in the exact order they arrive—spawns, events, network messages, or BFS neighbors—a Queue<T> is your best friend. It keeps your code clear, your logic predictable, and your performance steady. If you need LIFO instead, reach for Stack<T>; for random or bidirectional access, consider List<T> or LinkedList<T>.

That wraps up our three-part series on picking the right collection in Unity! Happy coding.

sour old man

Like what I said? Hate what I said?
Tell me what you think! kameron@creation-wasteland.com

SHARE: