Course contentsShow
← Unity Game Development
Lesson 476 of 8287. Advanced Game ArchitectureFree lesson

Decoupling Actions with the Command Pattern

Implement the Command pattern to encapsulate user inputs as objects, enabling features like input remapping, undo systems, and command queuing.

In this lesson, you will learn how to decouple your user inputs from game logic by wrapping requests into command objects.

The Problem: Tightly Coupled Input

In a standard Unity setup, you might check for input inside the Update() method of your PlayerController:

if (Input.GetKeyDown(KeyCode.Space)) {
    Jump();
}

This works for simple prototypes, but it creates a rigid link between the physical key and the character's behavior. If you want to add input remapping, an "undo" system, or record player actions for a replay, you’ll quickly find your PlayerController bloating with complex conditional logic.

The Command Solution

The Command Pattern transforms a method call into an object. Instead of directly calling Jump(), you create an object that represents the jump command.

First, define a simple interface:

public interface ICommand {
    void Execute(GameObject actor);
}

Now, create a concrete command for jumping:

public class JumpCommand : ICommand {
    public void Execute(GameObject actor) {
        actor.GetComponent<Rigidbody>().AddForce(Vector3.up * 10f, ForceMode.Impulse);
    }
}

Decoupling the Execution

By using this pattern, your input system no longer cares what the character is doing; it only cares about triggering the command. You can store these commands in a Queue<ICommand> to process them in order, or keep a Stack<ICommand> if you want to implement an "Undo" feature by adding an Undo() method to your interface.

This architecture decouples the Trigger (the input/UI button) from the Receiver (the player character). You can now swap the JumpCommand for a DashCommand dynamically at runtime, or record a sequence of commands to execute during a cutscene, all without changing a single line of code in your player movement scripts.

You’ve moved from "If this key is pressed, do this" to "If this key is pressed, dispatch this action object," making your code significantly more modular and testable.

Key Takeaway: By encapsulating actions as objects, you transform volatile user input into a flexible system capable of queuing, remapping, and reversing game events.