Quick Start: CommandHandler
The CommandHandler is perfect for adding undo/redo functionality to your Unity project. Use this when you need simple command execution without replay or deterministic features.
When to Use CommandHandler
- Simple undo/redo operations
- UI tracking (sliders, toggles, input fields)
- Non-deterministic gameplay
- Single-player experiences without replay
For turn-based games with replay support, see the CommandEngine Quick Start.
Installation
Import the DCE (Deterministic Command Engine) asset from the Unity Asset Store into your project.
Step 1: Create a Command
Commands implement the ICommand interface with three methods: Execute, Undo, and Redo.
using JFCreative.DCE.Core;
using System;
using UnityEngine;
public class MoveCommand : ICommand
{
private Transform _target;
private Vector3 _oldPosition;
private Vector3 _newPosition;
public MoveCommand(Transform target, Vector3 newPosition)
{
_target = target;
_oldPosition = target.position;
_newPosition = newPosition;
}
public void Execute(Action executedCallback)
{
_target.position = _newPosition;
executedCallback?.Invoke();
}
public void Undo()
{
_target.position = _oldPosition;
}
public void Redo()
{
_target.position = _newPosition;
}
}Step 2: Set Up CommandHandler
Create a CommandHandler instance in your game manager or controller:
using JFCreative.DCE.Core;
using UnityEngine;
public class GameManager : MonoBehaviour
{
private CommandHandler _handler;
private SystemTickSource _tickSource;
void Awake()
{
_tickSource = new SystemTickSource();
_handler = new CommandHandler(_tickSource, null, -1, true);
}
}Constructor Parameters:
- tickSource - Provides tick timing (required)
- recorder - Optional recorder for command history (null if not needed)
- maxCommands - Maximum undo history (-1 for unlimited)
- debug - Enable console logging for debugging
Step 3: Execute Commands
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
_handler.Execute(new MoveCommand(playerTransform, new Vector3(1, 0, 0)));
}
if (Input.GetKeyDown(KeyCode.Z))
{
_handler.Undo();
}
if (Input.GetKeyDown(KeyCode.Y))
{
_handler.Redo();
}
}Using CommandManager (Alternative)
For even simpler usage, add the CommandManager component to a GameObject in your scene. It provides static access to command operations:
using JFCreative.DCE.Core;
CommandManager.Execute(new MoveCommand(playerTransform, new Vector3(1, 0, 0)));
CommandManager.Undo();
CommandManager.Redo();The CommandManager component auto-ticks every FixedUpdate() and persists across scenes if configured.
Using Inline Commands
For quick operations, use the Command class without creating a dedicated class:
using JFCreative.DCE.Commands;
var health = 100;
var command = new Command(
execute: (callback) =>
{
health -= 10;
Debug.Log($"Health: {health}");
callback?.Invoke();
},
undo: () =>
{
health += 10;
Debug.Log($"Health restored: {health}");
}
);
_handler.Execute(command);UI Integration
The asset includes automatic UI tracking components:
UIUndoTracker (Standard UI)
Attach UIUndoTracker to any UI element to automatically track changes:
gameObject.AddComponent<UIUndoTracker>();Supports: Slider, Toggle, InputField, Dropdown
UIToolkitUndoTracker (UI Toolkit)
For UI Toolkit elements (24 element types supported):
using JFCreative.DCE.UI;
var tracker = GetComponent<UIToolkitUndoTracker>();
tracker.RegisterElement("MySlider");
tracker.RegisterElement("MyToggle");Property Commands
Use SetPropertyCommand to modify object properties with automatic undo/redo:
using JFCreative.DCE.Commands;
var cmd = new SetPropertyCommand<Player, int>(
player,
p => p.Health,
50
);
var cmd2 = new SetPropertyCommand<GameObject, Vector3>(
gameObject,
go => go.transform.position,
new Vector3(5, 0, 0)
);
_handler.Execute(cmd);Next Steps
- Create custom commands for your game logic
- Hook up undo/redo to UI buttons
- Use UIUndoTracker for automatic UI undo support
- Explore the Puzzle Game Sample for more examples
Ready for advanced features? Check out the CommandEngine Quick Start for deterministic replay, turn-based systems, and full recording capabilities.