In this lesson, you will learn how to architect a circular buffer to capture, store, and replay a sequence of player inputs, enabling features like frame-perfect replays or combo-recording systems.
The Core Concept: The History Buffer
At its simplest, an input history buffer is a collection that stores a series of ICommand objects over time. By using a "circular" or "fixed-size" buffer, we ensure the game doesn't crash from memory bloat during long play sessions; when the buffer reaches its limit, the oldest inputs are simply overwritten by the newest ones.
To make this reusable, we define a structure that captures the command itself and the exact timestamp or frame count it occurred.
Implementing the Buffer
Here is a simplified look at how to store these commands in a Queue structure:
public class InputHistoryBuffer
{
private Queue<CommandEntry> _history = new Queue<CommandEntry>();
private int _maxCapacity = 1000;
public void Record(ICommand command)
{
if (_history.Count >= _maxCapacity)
_history.Dequeue(); // Remove oldest to make room
_history.Enqueue(new CommandEntry(command, Time.frameCount));
}
public void ReplayAll()
{
foreach (var entry in _history)
{
entry.Command.Execute();
}
}
}
Decoupling for Replayability
By passing an ICommand into the buffer, we decouple the act of performing an action from the state of the game. Because your commands implement a standard Execute() method (as learned in our previous Command Pattern lesson), the buffer doesn’t need to know if the action was a jump, a sword swing, or a spell cast. It simply stores the interface.
To replay the sequence, the system iterates through the queue and triggers Execute() on each command. If you want to simulate real-time playback, you can use a Coroutine to wait for the difference in Time.frameCount between entries, recreating the player's exact timing. This approach allows you to implement "undo" features or ghost-recording systems without modifying your core player controller logic.
Key Takeaway: By storing serialized Command objects in a fixed-size queue, you create a memory-efficient and modular history system that can perfectly reconstruct gameplay sequences without tight coupling to game objects.