Creation Wasteland Logo

Unity Development: Use Stacks! (Part 2)

Category: Game Development

Published on 3/15/2025
By creationwasteland

SHARE:

In Part 1 we explored why List<T> isn’t always the best choice and dove into LinkedList<T>. In this Part 2 sequel, we’ll focus on Stacks—a Last-In-First-Out (LIFO) collection that shines in scenarios like undo systems, depth-first traversals, and nested state machines.

Understanding Stacks in Unity

What is a Stack?

A Stack<T> is a dynamic, LIFO data structure. You can only add or remove items at the “top” of the stack. The primary operations are:

  1. Push(T item): Place an item on top.
  2. Pop(): Remove and return the item from the top.
  3. Peek(): Inspect the top item without removing it.

Internally, .NET’s Stack<T> uses an array that grows by doubling its size when capacity is exceeded—providing O(1) amortized Push/Pop.

When to Use Stacks in Unity

Use stacks whenever you need to reverse or backtrack operations in a strict LIFO order:

  • Undo/Redo Systems: Record commands or states so the last action can be undone first.
  • Depth-First Searches: Perform graph or tree traversals without recursion.
  • State Machines & Nested Behaviors: Manage nested UI menus, game modes, or AI behaviors in a push/pop style.
  • Pooling & Resource Stacks: Quickly retrieve and return objects (e.g., bullets, particle effects).

Example: Building an Undo System with Stack<T>

Imagine a simple action interface and history manager:

// IAction.cs
public interface IAction {
  void Execute();
  void Undo();
}

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

public class HistoryManager : MonoBehaviour {
  private Stack<IAction> undoStack = new Stack<IAction>();
  private Stack<IAction> redoStack = new Stack<IAction>();

  public void DoAction(IAction action) {
    action.Execute();
    undoStack.Push(action);
    redoStack.Clear();
  }

  public void Undo() {
    if (undoStack.Count == 0) return;
    var action = undoStack.Pop();
    action.Undo();
    redoStack.Push(action);
  }

  public void Redo() {
    if (redoStack.Count == 0) return;
    var action = redoStack.Pop();
    action.Execute();
    undoStack.Push(action);
  }
}
  

Analyzing the Example and Performance Considerations

Key Takeaways

  1. Strict LIFO Order: Ensures the last action is always undone first.
  2. Constant-Time Operations: Push, Pop, and Peek are all O(1) amortized.
  3. Memory Growth: Internally doubles capacity, so occasional allocations occur but amortized cost stays low.

Stack vs. List

Stack Advantages:

  • Enforces LIFO discipline—no accidental random access.
  • Faster push/pop than inserting/removing at the end of a List<T> when capacity is sufficient.
  • Simplifies code for nested or reversible operations.

List Advantages:

  • Supports random access (list[index]).
  • Better for collections where you need to iterate in arbitrary order.
  • More flexible for mixed operations—insertions, deletions, lookups.

Conclusion: Choosing the Right Structure

When your Unity project demands strict LIFO behavior—like undo systems, DFS traversals, or nested states—Stack<T> is the clear winner. For everything else, weigh its constraints against the flexibility of List<T> or LinkedList<T>.

In Part 3 we’ll explore Queue<T> and real-time FIFO scenarios to further sharpen your data-structure toolkit.

sour old man

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

SHARE: