Experimental: Sample Code for Implementing Instant Replays

Article written by Alex K.

The Unreal Engine provides a Replay System for recording and playing back gameplay, offering a selection of streamers for recording and reading this data in a variety of ways. One of the streamers provided is The Memory Streamer, which can be used for implementing instant replays. This type of replay generally involves briefly playing back previous events within the game, such as a “kill-cam” in a multiplayer shooter, without breaking the flow of gameplay or loading a different level. While a feature like this is certainly possible to implement, the engine functionality used for such a feature is experimental and will require a fair amount of custom work within your project. This article seeks to provide a starting point for those trying to implement instant replays.

Generally, the Replay System loads a new level when a demo is played back. However, if you want to maintain the flow of gameplay when displaying an instant replay, the recommended approach involves creating a copy of the dynamic levels needed for playback. When activating the replay, you’ll then need to toggle the visibility of the game and replay “worlds” using level collections. The game net driver operates on the hidden set of actors in the background while viewing the replay, allowing the game state to be unaffected by the replay and allowing clients to remain connected to a server. To enable duplication of the levels you want, you’ll need to override UEngine::Experimental_ShouldPreDuplicateMap to return true for the appropriate levels. Level duplication is experimental, so enabling this feature may cause unforeseen issues within your project that you’ll need to debug.

It will also be up to your project to manage these level collections and handle switching between gameplay and the instant replay. This will require a custom implementation based on your project’s needs, and due to the experimental nature of this kind of feature, documentation and support are limited. In order to help with implementing this feature, attached here is the UKillcamPlayback manager class from Paragon that handled setting up the kill-cam recording, starting playback of the instant replay, and stopping playback to return to gameplay.

Within this class, there are a few key functions to check out. Setting up the kill-cam and starting the recording is handled mainly by SetUpKillcam_Internal. Starting playback is handled by a few functions. First is KillcamStart_Internal, which will call KillcamGoToTime. This function’s completion delegate, OnKillcamInitialGoToTimeComplete, will then call ShowKillcamToUser (which queues a task to call ShowKillcamToUser_Internal). Finally, stopping the playback is mainly handled by HideKillcamFromUser_Internal. It’s also worth noting that when calling these major tasks (SetUpKillcam, KillcamStart, ShowKillcamToUser, and HideKillcamFromUser), they are deferred until the next tick using a task queue.

It’s also worth noting that the original implementation of this feature was handled by duplicating the entire UWorld, with replays being played back in the duplicated world. This is the same method used by Unreal Tournament. To see how this type of kill-cam was implemented, you can check out UTKillcamPlayback.h/.cpp in the Unreal Tournament repository. For Paragon, this implementation was changed to only duplicating the dynamic source levels in order to save memory, but some references to this older implementation remain in the attached files, such as the “KillcamWorld” property.

This code should not be taken as a definitive “how-to” guide. It is several years old and may not even compile in a more recent version of the engine. It also relies on experimental features, and some of it is specific to how Paragon handled its kill-cam feature. That being said, hopefully these files can provide a useful starting point and reference when implementing this feature in your own project.

ExampleKillcamPlayback.zip (12.3 KB)


Can’t find the Paragon UKillcamPlayback manager class that is supposed to be attached? Got removed?

This has now been attached.

I can’t run this code because I can’t find killCamWorld. where can i get it?

Hey, might be dumb question but can’t get this off my head.
What would be the license for that code ?

I’m guessing lot of people will base their code on that and that could put them under potential liability.

Hi, I tried to implement an instant replay system using your sample.
And I got a “xxx.StaticMeshComponent0 was added to the wrong world’s scene (due to PIE). The callstack should tell you why” warnning.
Could you please give some hints?