Replays
Introduction
We added one way of saving and playing back replays with the Quantum to the 1.2.1. release.
Every part of the system comes in source code form.
You can inspect how it is implemented, use it as-is or tweak it to serve your project requirements in a better way.
By replay we are speaking about an unaltered compiled application that re-runs the game simulation with the exact same input, user input and game assets, from the recorded session.
The compiled application does not need to be the same one or even run on the same platform, e.g. Android, Unity Editor, Windows exe or your custom game server, but it has to be build with the same quantum dlls.
Thanks to determinism the played back game session will calculate the same results.
Replay Files
A replay consists of two parts:
- The database: Quantum static game asset from the (Unity)DB class (see Core/Replay/DatabaseFile.cs in quantum.state.csproj)
- The session specific configuration files and the input stream (see Core/Replay/ReplayFile.cs in quantum.state.csproj)
We split the replay into two files, because the database is fairly large and you need only one per game version (f.e. a released game or a QA build).
On the other hand you can have numerous replays per version.
When running a replay in Unity the UnityDB is loaded, but then gets swapped with the deserialized database from the replay.
Additionally all of the configs you see in the ReplayFile class are being replaced.

This is how a replay folder will look: Notice the Test_NavMeshUnity.bytes file?

We need to extract the actual navmesh data from the navmesh asset (see NavMesh:AssetObject
) because of the SciptableObject size limitation.
That is why the database is stored in a folder and not a single file.
For convenience reasons the replay file is located in the same folder.
When starting a replay in Unity. See below how the FileLoader, which is used to locate files on different platforms and environments (e.g. Unity Resources) from inside the Quantum code, is initialized with a path offset to point to the database folder.
C#
Quantum.FileLoader.Init(new Quantum.UnityFileLoader(DatabasePath));
Replay File Format
We chose to store the database in JSON and the replay files in JSON or BSON.
During development it always forthcoming to be able to humanly read files and the size does not matter too much here.
Like for example a QA ticket with a couple of MB attachment.
Replay files on the other hand you can optionally store in BSON, which already reduces the size a bit, but not enough to be production ready.
Compression helps here a lot, because the input is a binary blob which looks quite similar from frame to frame.
We are adding the default JSON .NET For Unity package from the asset store to the project.
If you already have it in your project just remove one version.
We also had to delete the JSON.net dll from the PUN package manually.
Setup For Replay Capturing
If you are running the game scene directly with the QuantumRunnerLocalDebug script: In the Inspector make sure that the RecordingFlags on the RuntimeConfig are set to Default
or at least Input
.
If you are running the game online for example via the Quantum sample menu scene: You are creating the RuntimeConfig dynamically and add the RecordingFlags there (e.g. UIRoom.CheckForGameStart()).
Saving A Replay
Now, you are able to use the replay menu items in the UnityEditor (see screenshot below, only usable when in Play mode).
A replay consists of multiple files (see section Replay Files) which are all stored in one folder.
If you are planing to run the replay in your application build, the replay folder needs to be located inside the Resource folder.

You can also use the QuantumSimpleReplaySaver script and add it to your game scene. It will let you store replays from within your application build: AltGr+R on Standalone, three finger touch on mobile. The replays are saved to AppData (Unity PersistentDataFolder).
You can always create your own way of saving replays if you feel there is a more convenient way.
Replay API
You can find most of the relevant replay methods in the QuantumGame class:
C#
public class QuantumGame : IDeterministicGame {
public InputProvider RecordedInputs { get; }
public ChecksumFile RecordedChecksums { get; }
public static void ExportDatabase(Stream stream, IReplaySerializer serializer, string folderpath, int navmeshSerializationBuffer);
public static void ExportRecordedChecksums(QuantumGame game, Stream stream, IReplaySerializer serializer);
public static void ExportRecordedReplay(QuantumGame game, Stream stream, IReplaySerializer serializer);
public ReplayFile GetRecordedReplay();
public Frame GetRecordedSnapshot(int frame);
public void StartRecordingChecksums();
public void StartRecordingInput();
public void StartRecordingSnapshots(float bufferSizeSec, int snapshotFrequencyPerSec);
public void StartVerifyingChecksums(ChecksumFile checksums);
}
Playback A Replay
We provide a script that works similar to the QuantumRunnerLocalDebug script, but performs all necessary actions the start and run a replay locally: QuantumRunnerLocalReplay.
- Add it to the same game object that QuantumRunnerLocalDebug script is located on.
- Activate only one of the two scripts when starting the game.
- Drag and drop the replay.json or replay.bytes file onto the replay runner script.
- If it locates the database file inside the same folder everything else gets filled out automatically.
- If not, drag the database file you want to use onto the script as well.
- Adding the checksum files there will validate the replayed frames (optional).

Look into the QuantumRunnerLocalReplay script to find all required information to use the replay API for running replays on your client.
Console Runner
With Quantum 1.2.2 you can add the quantum.console.runner project to your quantum_code.sln.

Select it as start-up project and you are able to press F5 and debug your Quantum simulation without Unity with the passed in replay files:
console.runner.exe [folder path to LUT files] [file path to database] [file path to replay] ([file path to checksums])
The project already set up the following paths in debug mode.
../../../../quantum_unity/Assets/Quantum/Resources/LUT
../../../../quantum_unity/Assets/Resources/Replays/replay/db.json
../../../../quantum_unity/Assets/Resources/Replays/replay/replay.json
../../../../quantum_unity/Assets/Resources/replay/checksum.json
When passing a checksum file you might encounter verification errors. The recorded checksums with Unity are not compatible with the ones generated in the runner. Activate ChecksumCrossPlatformDeterminism
on your DeterministicConfig and record the replay again to fix the errors or don't pass the checksum file at all.
Please note that the console runner uses:
- The Quantum dlls (PhotonDeterministic, core) from the assemblies folder
- Your Quantum game dlls (state, systems) from the Unity plugins folder (so you might need to update the reference link in the cs-project if you changed the project layout or renamed the quantum_unity folder)
- Newtonsoft.Json nuget package