Creating a Replay System in Unity
A replay system is a great way to let players relive their best (or worst) moments of gameplay, improve their strategy, and more! In this tutorial, you’ll build a simple state-based replay system and learn about how replay systems work. By Teddy Engel.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Creating a Replay System in Unity
25 mins
- Getting Started
- What is a Replay System?
- Choosing the Approach: State-based or Input-based
- What is State-based Replay?
- Pros and Cons of State-Based Replay
- What is Input-based Replay?
- Pros and Cons of Input-Based Replay
- Deterministic vs Non-Deterministic Game Engines
- Setting Up to Record
- Finding the Transforms
- Recording Action Frames
- What is a MemoryStream?
- Setting up a MemoryStream
- Starting at the Beginning
- Writing Transform Positions to the Stream
- Replaying Action Frames
- Starting at the Beginning
- Reading Positions From the Stream
- Recording the Direction
- Optimizing Memory Usage
- Capping Replay Duration
- Challenge: Skipping Frames
- Counting Frames
- Using the Counter
- Where to Go From Here?
- Reference
A replay system is a great way to let players relive their best, or worst, moments of gameplay, improve their strategy and more!
You could choose to use one from the Asset Store, but I’ll assume you’re reading this wearing a red bandana and with an army knife between your teeth, ready for a challenge. :]
In this tutorial, you’ll learn:
- What a replay system is.
- The difference between state-based and input-based replay systems.
- How to implement a state-based replay system from scratch.
Getting Started
Download the project files by clicking the Download Materials button at the top or bottom of this tutorial.
Go to RW/Scenes and open the Main scene. It’s already set up with a sprite, a character controller, buttons for the replay system and some catchy 8-bit music.
Press the Play button and give it a go. Control Birdy by using the left and right arrows and space bar to jump.
Click the Start recording / Stop recording and Start replay / Stop replay buttons. The buttons update when you click them, but the system doesn’t actually record or replay anything yet. That’s where you’ll come in. :]
What is a Replay System?
A replay system is an in-game system that lets the player record a gameplay sequence and replay it, just like recording a video with a phone and playing it again.
For the purposes of this tutorial:
- Record means to capture a sequence of frames rendered by the game.
- Replay means to play back the captured sequence, in the same order, from the beginning.
- The system will only capture one sequence at a time. Pressing Record again will overwrite the previous sequence.
- The system will record the sequence in RAM. This tutorial doesn’t cover saving and loading a sequence from the disk.
- Player input will still be active during the replay playback. This won’t be a big issue anyway as you’ll update the states every frame.
Choosing the Approach: State-based or Input-based
There are two popular types of replay systems: State-based and input-based. While they do the same thing, each approach has its pros and cons. SO, what’s the difference?
What is State-based Replay?
When you record with a state-based system, you capture a sequence of states. A state is a snapshot of the properties of an entity.
For example, in a Unity game, you might want to record and replay the position of the player character and their awesome boomerang weapon.
At frame 1, you’d record these positions:
- Player character: (X:0, Y:1, Z:0)
- Boomerang: (X:0, Y:2, Z:1)
When Unity processes the next frame of gameplay, both objects move. So, for frame two you’d store these values:
- Player character: (X:0, Y:1, Z:1)
- Boomerang: (X:1, Y:1, Z:1)
If the player is Object 1 and the boomerang is Object 2, the memory would look like this:
In a state-based system, you replay the states by reading the frames in order and applying the saved values to your GameObjects.
So, if you were replaying the data above, at frame one you’d assign these positions:
- Player character: (X:0, Y:1, Z:0)
- Boomerang: (X:0, Y:2, Z:1)
At frame two, you’d assign these positions:
- Player character: (X:0, Y:1, Z:1)
- Boomerang: (X:1, Y:1, Z:1)
And so on for as many frames as you’ve saved.
Pros and Cons of State-Based Replay
The main advantages of a state-based system are:
- Determinism: It’ll always give the same output, even if the underlying engine is non-deterministic.
- Replay filtering: You’re able to select with great granularity what you want to record. For example, you could record and replay only the player position, while things like tree leaves and clouds still move independently.
- Simplicity: It’s simple to implement.
- No context needed: It’s easy to replay at anytime. You don’t have to set up a scene context first.
The main weakness is:
- Memory footprint: If you start recording a lot of states, for example, a lot of frames, the replay’s memory usage of will skyrocket.
Time to look at the input-based approach to compare.
What is Input-based Replay?
When you record with an input-based system, you capture the initial state of your objects, then capture a sequence of inputs. Inputs might be touch gestures, joystick values or keypresses, depending on your game.
Instead of recording the state of individual GameObjects each frame, you record their state only once, in the very first frame of the game. Then you store the inputs that might alter their states.
For example, at the beginning of your game you’d store the positions of all the GameObjects you’re including in the replay. If your player moves to the right and then crouches in frame one, you’d record the information like this:
- At frame zero, which isn’t shown, you record the state of the entire scene.
- You record a directional input to the right and a directional input down at frame one.
- At frame two, you record a directional input down.
- You record a directional input down at frame three.
When you replay with an input-based system, first you set the entire state back to what it was at the beginning of the playback. Then, in each frame, you apply the inputs you recorded for that frame.
In this example, at frame zero, you’d reset the scene state, So, you’d read all of the states you recorded at frame zero and write the information back to your GameObjects. At frame one, you’d simulate a directional input to the right and down, at frame two a directional input down and so on for all the frames of input you’ve recorded.