All projects
Project 02 · Unreal · C++, Python

Time to Breach

Role: Time Rewind System

Time to Breach is a CRPG with a player-only rewind mechanic. The player can scrub back along their own timeline—position, rotation, velocity, and selected player variables—while the world and enemies continue forward in normal time. This is a true state rewind of the player, not a cinematic effect.

Time to Breach: an armoured soldier holding a rifle

Project Overview

Project Type
CRPG
Role
Time Rewind System
Team Size
8 people
Duration
4 Weeks
Engine
Unreal
Language
C++, Python

System Breakdown

The rewind system stores two different kinds of data: continuous motion state and discrete gameplay events.
Separating these keeps memory stable and avoids unnecessary data recording.

1) Continuous State (Ring Buffer)

The component samples the owner’s state at a fixed interval and stores each snapshot in a constant-size ring buffer. This keeps memory usage stable and prevents unbounded growth over long sessions.

Each snapshot contains:

  • World transform
  • Linear velocity
  • Angular velocity
  • Movement mode + movement input velocity (used to drive correct animation state during rewind)

When rewind is active:

  • Physics simulation is disabled on the actor
  • Snapshots are read backwards through the ring buffer
  • The actor is positioned using interpolation to avoid visual snapping or jitter

This recreates the player's physical motion in reverse, smoothly.

2) Event Timeline (Health Only in This Project)

Discrete gameplay changes are not stored every frame.
Instead, the system records health change events with timestamps.

During rewind:

  • The timeline is stepped backwards
  • Any health change that occurred during the rewind window is undone

The system is structured so additional reversible events (resources, status flags, etc.) could be added the same way, but only health was implemented in this project due to scope.

Continuous motion is reversed mathematically.
Health changes are reversed logically.

Editor Workflow Support (Python)

A small Unreal Python tool was written to automatically generate reversed animation assets (AnimSequences and Montages) for testing rewind animation playback. This allowed animation variations to be batch-processed instead of duplicated by hand.

Code

void URewindComponent::RecordSnapshot(float DeltaTime)
{
    TimeSinceSnapshotsChanged += DeltaTime;
    LocalTimeFromStart += DeltaTime;

    // sample at fixed frequency
    if (TimeSinceSnapshotsChanged < SnapshotFrequencySeconds &&
        TransformAndVelocityRecentHistory.Num() != 0)
        return;

    // ring buffer: drop oldest when full
    if (TransformAndVelocityRecentHistory.Num() == MaxSnapshots)
        TransformAndVelocityRecentHistory.PopFront();

    const FTransform T = GetOwner()->GetActorTransform();
    const FVector Lin = OwnerRootComponent
        ? OwnerRootComponent->GetPhysicsLinearVelocity() : FVector::ZeroVector;
    const FVector Ang = OwnerRootComponent
        ? OwnerRootComponent->GetPhysicsAngularVelocityInRadians() : FVector::ZeroVector;

    LatestSnapshotIndex =
        TransformAndVelocityRecentHistory.Emplace(LocalTimeFromStart,
                                                  TimeSinceSnapshotsChanged,
                                                  T, Lin, Ang);

    // optional animation sampling (if enabled)
    if (bSnapshotAnimationVariables && OwnerMovementComponent)
    {
        if (AnimationRecentHistory.Num() == MaxSnapshots)
            AnimationRecentHistory.PopFront();

        AnimationRecentHistory.Emplace(LocalTimeFromStart,
                                       TimeSinceSnapshotsChanged,
                                       OwnerMovementComponent->Velocity,
                                       OwnerMovementComponent->MovementMode);
    }
    TimeSinceSnapshotsChanged = 0.f;
}
Core snapshot recording into a fixed-size ring buffer; optional animation state captured for correct rewind playback.

Results

  • The player rewind mechanic worked reliably and remained visually smooth due to interpolation during playback.
  • The ring buffer kept memory usage fixed and allowed rewind duration to scale predictably from game settings.
  • The component could be added to any actor without additional setup, enabling reuse beyond the original design.
  • The health event rewind restored player state consistently, avoiding desync between animation/motion reversal and gameplay effects.
  • World state and enemy behavior continued in forward time while the player rewound, preserving clarity and spatial awareness in combat.

If I Had More Time

  • Extend Event Timeline beyond health to include ammunition, cooldowns, and status flags using the same reversible event pattern.
  • Generalize Animation Rewind for montage-based actions (e.g., firing, rolling) so the animation layer matches the reversed motion more precisely.