For my small horror game I needed to save some data for the secrets in the game to work properly. I like to manage save data the same way that some old games do, as I find it’s an incredibly simple but effective way to do it.
So for Escape Floor Zero I created a SaveGame object in Unreal and there I created a single variable: A Map of Names to Integers.
Let’s build that save system in Blueprint.
Create a SaveGame Blueprint and SaveData Map
To create a Save Game Object in Unreal, right click on the content browser and then choose the Blueprint category. Once there, search for SaveGame and click it.

This will create a new SaveGame object in your content browser, you can name it whatever you like. All your game save data will live here.
Press ”+” on the right of the Variables section to create a variable.

I will call it SaveData, though you can use any name. Set its type to a Map of Names to Integers.

And with this our Save Object is ready on the data part.
Load an Existing Save Game or Create a New Save
Our SaveGame class is ready, now we need to use it.
The first thing we need to do is to create it or load it once the game starts. This can be done in many places ( Game Instance, Game Mode, Custom Logic… ). In this case we will do it in the Begin Play function of our Game Mode.

Let’s break a little bit down what we are doing here:
- First we are trying to load a SaveGame file called “SaveData” ( this has nothing to do with the variable of the same name, this is the name of the actual file that will exist in the disk )
- If the file is found, the SaveGame is loaded, so we Cast it to our SaveGame type that we created and assign it to a variable, to be used later
- If the file is not found, this means that no SaveData exist, in this case we create a SaveGame of the type we want, store it in a variable, and write it back into disk
We now load the existing save into memory, or create one if there is no file yet.
Read and Write Data in the SaveGame Object
Now that the system is ready, let’s see how we can read and write data to it.
Everything goes in the SaveGame object’s SaveData map. Give each piece of data a name and store its integer value:
- Player.NumDeaths -> 3: This will store that the player has died 3 times
- VisitedLocations.SuperCoolCity -> 1: This will store that the location “SuperCoolCity” has been visited
- NPC.TownVendor.ShopLevel -> 5: The shop level for the town shop npc is at level 5
- World.DefeatedEnemies.Dungeon07.DragonMonster07 -> 1: A specific monster at a specific location is dead
The same map can hold all of these. Let’s write a value to it.
We stored the SaveGame object in a Game Mode variable earlier. To make it easier to use, we can add functions to the SaveGame object itself, since it is a Blueprint Object.

In the end, internally we are doing this:

We are inserting the value in the map and then we are writing the file to disk.
You will notice that in the function I created, I added a “PerformSave?” input. This is because writing a file to disk can be expensive, so instead of always writing to disk, we can keep those changes in memory, and only write to disk in certain cases, like after some time, or if you defeat a boss, or other important events.
Reading SaveGame data is even easier, as it’s simply finding it in the map.

The boolean output will tell us if the value even exists and the integer output will be the value itself.
That gives us the read and write functions for the save system.
The map holds flags and counters. Structs, transforms and floats need extra work. There is no save-format versioning either, so renaming a key or changing its meaning means handling migration for old saves yourself.
I have left async saving and multiple slots out of this example. For a small game these may not matter much, but I would plan for them on a bigger project.
Lots of games use a system like this. If you know Pokemon or RPG Maker, you’ll recognize it, it’s close to how they track state. Bigger games do the same thing at a larger scale: that’s roughly how Zelda: Breath of the Wild stores the enemies you’ve defeated, the locations you’ve visited, and its quest and world state.


Recap
The save data lives in one SaveGame object, in a Map of Name to Integer. Keys such as “Player.NumDeaths” and “World.DefeatedEnemies.Dungeon07” let us organize it ourselves. On Begin Play we load the file, or create and write a new save if it does not exist.
The part to be careful with is writing to disk. Keep changes in memory until an event that should save them; that is what the “PerformSave?” input is for.


