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:
- Enqueue(T item): Add an item to the end.
- Dequeue(): Remove and return the item at the front.
- 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
- Strict FIFO Order: Ensures spawn requests fire in the order they were made.
- Constant-Time Operations:
Enqueue,Dequeue, andPeekareO(1)amortized. - 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.
