Rewind Controller

Rewind actions in Unity.
https://github.com/GandhiGames/rewind_controller
0 forks.
0 stars.
0 open issues.
Recent commits:

 

What is it?

This project provides a method of implementing a rewind effect in a game, popularized by games such as Braid.

A scene from the popular video game Braid. The player is using the rewind ability.
Braid makes extensive use of a Rewind ability as a core game mechanic.

The rewind ability in this project is made possible due to the Command Pattern, which makes implementing a rewind ability surprisingly easy.

All actions in the scene (including player/enemy movement, deaths, projectile release/movement) are encapsulated as actionable command objects. The base Command class is shown below.

/// <summary>
/// Base abstract command. All commands (e.g. movement, attack) should inherit form this class.
/// </summary>
public abstract class Command
{
protected Transform character;
protected Vector2 dir;
public Command (Transform character = null, Vector3 dir = default(Vector3))
{
this.character = character;
this.dir = dir;
}
/// <summary>
/// Perform the action.
/// </summary>
public abstract void Execute ();
/// <summary>
/// Perform the reverse action.
/// </summary>
public abstract void Undo ();
}

Each command has an execute and undo method. For example, implementation of a simple movement command is shown below.

public class MovementCommand : Command
{
private Vector2? undoDir;
public MovementCommand (Transform character, Vector2 dir) : base (character, dir)
{
}
public override void Execute ()
{
undoDir = -dir;
character.Translate (dir, Space.World);
}
public override void Undo ()
{
if (undoDir.HasValue)
character.Translate (undoDir.Value, Space.World);
}
}

When a command is generated it is added to a global group containing all commands executed.

rewind.AddCommand (new MovementWithPhysicsCommand (transform, amountToMove * Time.deltaTime, physics), true);
rewind.AddCommand (new ClimbLadderCommand (this, true), true);

This group simply encapsulates a list and provides access to a Reverse method (important in undoing the performed actions).

public class CommandGroup
{
private List<Command> commands = new List<Command> ();
public void Add (Command command)
{
commands.Add (command);
}
public void Remove (int index)
{
commands.RemoveAt (index);
}
public Command Get (int index)
{
return commands [index];
}
public int Length ()
{
return commands.Count;
}
public List<Command> Reverse ()
{
commands.Reverse ();
return commands;
}
}

To reverse the scene (and begin the rewind effect), you simply iterate through the command group in reverse order and execute the commands undo methods.

/// <summary>
/// Checks if it is ok to undo and calls the most recent commands undo method. 
/// The command list is traversed from most recent to first.
/// When current command is less than 0 the complete flag is set to true.
/// This will stop the rewind process and enable the character to run new commands.
/// </summary>
protected override void Execute ()
{
if (CancelRequested ()) {
Reset ();
return;
}
foreach (var command in commands[currentGroup].Reverse ()) {
command.Undo ();
}
commands.RemoveAt (currentGroup);
currentGroup--;
if (currentGroup < 0) {
Reset ();
return;
}
}

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *