Save Game: Create / Save / Load Game to Slot¶
At a glance
Lives in: Blueprint API / SaveGame - Target: Gameplay Statics -
Returns: Create Save Game Object returns a new SaveGame object;
Save Game to Slot returns Boolean; Load Game from Slot returns a
SaveGame object or None - Changes: writes or reads a platform save
slot only when you call the save/load nodes - Can fail by: wrong class,
wrong slot/user index, missing slot, disk/platform write failure, bad cast,
or trying to persist live actor references - Official docs:
Saving and Loading Your Game,
Create Save Game Object,
Save Game to Slot,
and
Load Game from Slot
The one-minute version¶
- A SaveGame object is a data object you design. It is not the current world, not a checkpoint system by itself, and not automatic serialization of every actor.
- Create a Blueprint subclass of
SaveGame, add variables to it, create an object of that class, copy values into it, then callSave Game to Slot. - Loading is the reverse: load the object from the same slot/user index, cast it to your SaveGame class, then copy values back into the current world.
- Use
Does Save Game Existbefore loading when a missing save slot is normal, such as a first launch or a new profile. Save Game to Slotreturnstrueorfalse. Treatfalseas "the save did not complete" and keep the player out of destructive follow-up actions.- Use the async save/load variants for autosaves, large saves, or moments where a hitch would be visible. Use the sync nodes for small menu saves while paused.
- Do not design around storing live actor references. Store IDs, names, plain values, classes, transforms, and map names, then rebuild live references after the map loads.
What it actually is¶
USaveGame is a base object class meant to hold data that can be serialized to
a platform save slot. In Blueprint, the normal setup is:
Content Browser
-> Add Blueprint Class
-> All Classes
-> SaveGame
-> name it BP_MySaveGame
-> add variables such as Coins, CurrentLevelName, PlayerTransform, DoorStates
The object is just memory until you save it:
Create Save Game Object
-> returns a new empty BP_MySaveGame object in memory
-> you set variables on it
-> Save Game to Slot writes that object to the chosen slot
Nothing in the current world is copied automatically. If the player has 12
coins on the Character and you never assign SaveObject.Coins = 12, the save
object does not magically know about the Character's value.
The three-node workflow¶
For a first save button:
Save button clicked
-> Create Save Game Object (Save Game Class = BP_MySaveGame)
-> Cast To BP_MySaveGame
-> Set Coins = CurrentCoins
-> Set CurrentMap = current map name
-> Set PlayerTransform = player transform
-> Save Game to Slot
Save Game Object = BP_MySaveGame object
Slot Name = "Profile_0"
User Index = 0
-> Branch on Return Value
For first launch/load:
Main menu Continue clicked
-> Does Save Game Exist (Slot Name = "Profile_0", User Index = 0)
-> Branch
false: start a new game path
true:
Load Game from Slot
Is Valid Return Value
Cast To BP_MySaveGame
read CurrentMap / Coins / PlayerTransform
put runtime handoff values in Game Instance
Open Level saved CurrentMap
Then in the loaded map:
PlayerController BeginPlay
-> Get Game Instance
-> read loaded save values needed for this map
-> move/spawn/initialize current pawn
-> update HUD
That last step matters. The SaveGame object is durable data. The current pawn, HUD, doors, enemies, and pickups are live world objects. Your Blueprint decides how saved data becomes live state.
The pins that matter¶
Save Game Class¶
This is the SaveGame subclass to create. It should be your BP_MySaveGame
class, not a pawn, widget, actor, GameMode, or Game Instance class.
If the class is wrong, the object may be unusable for your save data, and a later cast to your expected class will fail.
Save Game Object¶
This is the object to write. You normally pass the object returned by
Create Save Game Object or the object returned by Load Game from Slot after
you update its variables.
Saving an old object saves that old object's current values. Saving a newly created object before setting variables saves defaults.
Slot Name¶
The slot name is your save-file key. Use a stable string such as:
Profile_0
Autosave
Checkpoint_CaveEntrance
Changing the string creates or reads a different slot. Most "my load is empty" bugs are really "save used one slot name, load used another."
User Index¶
User Index is a platform user number. Many single-player PC projects use 0.
Epic's docs note that some platforms ignore it, but you should still pass the
same value for save, existence check, and load.
Return values¶
| Node | Return value | Meaning |
|---|---|---|
| Create Save Game Object | New SaveGame object | A blank object in memory; not written to disk yet. |
| Save Game to Slot | true / false |
Whether the write succeeded. |
| Does Save Game Exist | true / false |
Whether a slot exists for that slot/user pair. |
| Load Game from Slot | SaveGame object or None |
Loaded data object if the read succeeded; None if it failed. |
Always branch on save success when the next step matters. For example, do not
delete an old checkpoint, show "saved," or travel away from an unsaved menu
unless the save returned true.
What to store¶
Good beginner SaveGame variables:
| Need | Store this |
|---|---|
| Resume a map | Map name or soft reference to the map. |
| Restore player position | Transform, checkpoint ID, or spawn entrance ID. |
| Restore inventory | Item IDs, counts, equipped item ID/class, ammo values. |
| Restore doors/pickups | Durable IDs plus opened/collected booleans. |
| Restore settings | Plain values such as volume, invert Y, subtitles. |
| Restore selected character | Class reference or asset ID, not the old pawn object. |
Poor SaveGame variables:
- direct references to placed actors in a map;
- references to the current pawn, controller, widget, or component;
- values that change every frame but do not matter after load;
- temporary combat state that should reset on death or map start;
- huge object graphs "just in case";
- secrets or anti-cheat-sensitive data that should not be trusted from a local save file.
The quick path is to put every variable you can see into the SaveGame class. The concrete cost is that loading becomes a second, hidden version of your whole game state. Save durable facts and rebuild the live world from those facts.
Actor references are the trap¶
A live actor reference points at an object in a loaded world. Save files outlive that world. Even when a reference-shaped value appears to serialize in a test, it is usually the wrong design for beginner saves because the live actor may not exist when you load, may have a different generated instance name, or may belong to another map.
Use durable identity instead:
Bad save data:
DoorReference = BP_Door_12 live actor
Better save data:
DoorStates:
DoorId = "Cave_Entrance_Door"
bOpened = true
On map BeginPlay, each door can look up its own ID in the loaded data and apply the saved state. The save stores facts. The map rebuilds actors.
For player position, storing a transform can be fine:
Save:
CurrentMap = "L_Cave"
LastCheckpointId = "Entrance"
SavedPlayerTransform = X/Y/Z + rotation
Load:
Open Level L_Cave
after map starts, move/spawn player at that checkpoint/transform
If collision matters, restore the player with the same care you would use for normal spawning or movement. Do not blindly place the character inside a wall.
Sync vs async¶
The synchronous nodes are simple:
Save Game to Slot
-> waits for the save attempt
-> returns true/false
They are fine for small saves from a pause menu, main menu, or checkpoint moment where a short hitch is acceptable.
The async variants are for smoother runtime behavior:
Async Save Game to Slot
-> starts the save
-> game can continue
-> completion callback gives Slot Name, User Index, and success boolean
Use async for autosaves, larger save objects, or saving during active gameplay. While an async save is in progress, avoid starting another write to the same slot unless your own save manager serializes those requests. "Last write wins" bugs are difficult to reason about when two systems save different versions of the object.
SaveGame vs Game Instance¶
These two are often used together, but they solve different lifetimes.
| Need | Use |
|---|---|
Survive Open Level during the same running game |
Game Instance |
| Survive quitting and launching later | SaveGame |
| Current map rules/default pawn | GameMode |
| Current pawn health/movement/body state | Pawn, Character, or a component |
| UI references and menu widgets | PlayerController, HUD, or widgets |
A clean pattern is:
Load save from disk
-> copy needed runtime values into Game Instance
-> Open Level saved map
-> destination map reads Game Instance and initializes live actors
-> when saving again, copy current live values back into SaveGame
-> Save Game to Slot
Game Instance is the handoff while the application is running. SaveGame is the disk record.
What the SaveGame flag does not do here¶
Blueprint variables can expose a SaveGame flag in some contexts, and C++
properties can be marked for save-game serialization. That flag matters for
systems that deliberately serialize only save-marked properties.
Epic's Save Game to Slot Blueprint helper writes the SaveGame object's
non-transient properties; its official page explicitly notes that the helper
does not filter by the SaveGame property flag. For a Blueprint beginner, the
practical rule is simpler:
Only values that are on the SaveGame object, and that you set to the values you
care about, are part of this save-object workflow.
Do not rely on a checkbox to pull data out of your Character, GameMode, or level actors. Copy the values.
When it fails (and what failure does)¶
Common causes:
- You loaded a missing slot.
Load Game from SlotreturnsNone; useDoes Save Game Existwhen absence is expected. - Save and load use different slot names or user indexes. The data exists, but you are asking for another key.
- The loaded object is not your class. The cast fails because the slot was created with another SaveGame class or old data.
- You saved defaults. You created the object but did not copy current values into it before saving.
- The write failed. Disk/platform conditions, permissions, storage
limits, or platform user state can make
Save Game to Slotreturnfalse. - You stored live object references. Loading gives you stale or unusable references instead of rebuildable state.
- You loaded before the destination world exists. Read durable data first, travel, then apply map-specific data after the new map starts.
- You changed the SaveGame class layout. Old saves may not contain new variables or may need version/default handling.
Failure does not run a special failed exec pin on the sync nodes. The graph continues with a return value. Branch on it, print the slot/user values, and guard loaded objects with Is Valid before casting.
The C++ twin¶
For the curious, the C++ version follows the same shape (our own example code):
void UTrainingSaveSubsystem::WriteSlot(const FString& SlotName, int32 Coins)
{
UTrainingSaveGame* Save =
Cast<UTrainingSaveGame>(UGameplayStatics::CreateSaveGameObject(
UTrainingSaveGame::StaticClass()));
if (!IsValid(Save))
{
return;
}
Save->Coins = Coins;
Save->LastMapName = FName(TEXT("L_Cave"));
const bool bSaved =
UGameplayStatics::SaveGameToSlot(Save, SlotName, 0);
if (!bSaved)
{
UE_LOG(LogTemp, Warning, TEXT("Save failed for slot %s"), *SlotName);
}
}
Lookalikes - which one do I want?¶
| Node or tool | Use when | Not the same as |
|---|---|---|
| Create Save Game Object | You need a new in-memory object of your SaveGame class. | Writing to disk. |
| Save Game to Slot | You want to write the object to a platform save slot now. | Automatically collecting world state. |
| Does Save Game Exist | Missing save data is normal and you need to branch. | Validating that the data inside is the right version/class. |
| Load Game from Slot | You want to read saved data from a slot. | Applying that data to live actors for you. |
| Async Save / Async Load | Save/load should not hitch active gameplay. | Simpler graph control flow. |
| Delete Game in Slot | You intentionally remove a save slot. | Resetting current runtime variables by itself. |
| Game Instance | Runtime values must survive map travel. | Data that survives quitting. |
| Open Level | You want to load the saved map or travel after saving. | Saving data. |
Going deeper¶
- Game Instance - runtime handoff data that survives Open Level but not quitting.
- Open Level - loading the destination map after you choose or load save data.
- GameMode & friends, single-player edition - why the new map's framework objects are recreated.
- Get Player Character / Pawn / Controller - rebuilding live references after load/travel.
- Is Valid - guarding load results and optional runtime references.
- Official docs: Saving and Loading Your Game, USaveGame, Create Save Game Object, Save Game to Slot, Load Game from Slot, and UGameplayStatics.
- Engine source (requires engine access - we do not reproduce it here):
USaveGameis declared inEngine/Source/Runtime/Engine/Classes/GameFramework/SaveGame.h;UGameplayStatics::CreateSaveGameObject,UGameplayStatics::SaveGameToSlot,UGameplayStatics::LoadGameFromSlot,UGameplayStatics::DoesSaveGameExist, and the async save/load helpers are declared inEngine/Source/Runtime/Engine/Classes/Kismet/GameplayStatics.hand implemented inEngine/Source/Runtime/Engine/Private/GameplayStatics.cpp.