Hit enter to search or ESC to close

Saving Screenshots & Byte Data in Unreal Engine

Kazimieras

Unreal Engine 4 has a platform-agnostic save game system that can serialize all core data types and even nested objects through pointers. So long as we declare all data we want to save as object properties, the system will work out of the box. But sometimes we want to save binary data from transient resources or arbitrary blocks of memory. In this Devlog entry, we will be exploring one such scenario by embedding a screenshot texture in our save game.

As usual, this post will cover a broader range of useful topics and best practices. We will go over the entire process of building an actor that we will use to save and load our game with an embedded screenshot. The first part of this process – taking a screenshot to memory in Unreal Engine – is already up on Devlog, so go ahead and give it a read if you haven’t yet. In this entry, we will be focusing on the second part: saving and loading arbitrary memory data to and from disk using UE4’s save game system.

Save Game Objects in Unreal Engine

The save game system in Unreal Engine is very robust. It enables saving and loading an object with a set of properties from files with just a few lines of code. What is even better, the engine writes our data to save slots in a platform-agnostic way, which means that whether your game targets PC, console, or mobile, UE4 will entirely handle the hardware abstraction.

By default, Unreal Engine will agreeably serialize most data types that we can declare as object properties when we ask it to save our objects, and all properties that aren’t marked with the Transient specifier will be serialized. This system will even serialize properties of objects that our declared properties point to. But it will never attempt to serialize anything that is not declared as an object’s property. We can change all of this default behavior with custom Serialize function overrides. But that is a topic for another Devlog.

Robust as the default behavior is, it still presents a problem when we wish to save things like transient textures or chunks of raw memory we generate at runtime. That is because neither bulk data of resources nor arbitrary bits of memory are UPROPERTIES. If we simply declared a property like

UPROPERTY(VisibleAnywhere, SaveGame)
    UTexture2D * SavedTexture;

in an object we serialize, upon unserialization, a UTexture2D will be created, but the original resource might be long gone if the transient package was destroyed. The same goes for all pointers to memory. We can restore a pointer, but who is to say that upon loading the game, the memory block still contains the same data as when our game was saved?


Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.