ue-serialization-savegames
Use when implementing save/load systems, player progress persistence, or data serialization in Unreal Engine. Triggers on: save game, USaveGame, FArchive, serialization, SaveGameToSlot, config, persist data, save file, load game. See references/save-system-architecture.md for full slot management an
By quodsoler · 789 installs
npx skills add quodsoler/unreal-engine-skills --skill ue-serialization-savegames
Source repository · Upstream listing
UE Serialization & Save Games
You are an expert in Unreal Engine's serialization and save game systems. You implement save/load pipelines using USaveGame , FArchive , config files, and versioning so player progress persists correctly across sessions and game updates.
Step 1: Read Project Context
Read .agents/ue project context.md before giving any recommendations. You need:
Engine version (UE 5.0+ has ULocalPlayerSaveGame ; earlier versions differ)
Module names (the save system lives in a specific module)
Target platforms (console vs. PC save paths and user indices differ)
Whether multiplayer is in scope (server authoritative vs. client local saves)
If the file does not exist, ask the user to run /ue project context first.
Step 2: Gather Requirements
Ask before writing code:
1. Save complexity : Simple key/value data, or complex world state with hundreds of objects?
2. Data types : Primitives, nested structs, asset references (soft vs. hard)?
3. Versioning needs : Live game with future patches? Old saves must keep working?
4. Multiple save slots : How many? Does each player/user get their own?
5. Async requirement : Can save/load stall the game thread, or must it be background?
Step 3: USaveGame Subclass
USaveGame is an abstract UObject from GameFramework/SaveGame.h . Subclass it and mark fields with UPROPERTY(SaveGame) for automatic tagged serialization by UGameplayStatics .
Saving and Loading
Step 4: ULocalPlayerSaveGame (UE 5.0+)
ULocalPlayerSaveGame ties a save to a specific local player, tracks versioning via GetLatestDataVersion() , and provides HandlePostLoad() for migrations.
Step 5: FArchive and Custom Serialization
FArchive (from Serialization/Archive.h ) is the base for all UE serialization. Key API:
FMemoryWriter and FMemoryReader
FMemoryWriter / FMemoryReader (from Serialization/MemoryWriter.h / MemoryReader.h ) serialize to/from TArray<uint8 :
FBufferArchive
FBufferArchive (from Serialization/BufferArchive.h ) combines FMemoryWriter + TArray<uint8 — the object is the output buffer:
Custom operator<< for Structs
Define operator<< to make a struct serializable via any FArchive (required when passing it to FBufferArchive , FMemoryWriter , etc.):
Compressed Archives
For large saves, use FArchiveSaveCompressedProxy / FArchiveLoadCompressedProxy (from Serialization/ArchiveSaveCompressedProxy.h ):
Custom Serialize() on UObject
Override Serialize(FArchive& Ar) for precise binary layout control:
Step 6: Versioning
Integer Versioning in USaveGame
FCustomVersionRegistration (FArchive based saves)
Struct Field Migration
When a struct field is renamed or its type changes, override Serialize() on the struct to migrate old data:
Step 7: Config Files
UGameUserSettings (user preferences)
UDeveloperSettings (project settings)
GConfig Direct Access
INI section naming : Section [/Script/ModuleName.ClassName] maps to the CDO. SaveConfig() writes from the object to INI; LoadConfig() reads INI into the object and is called automatically for the CDO at startup. Custom section names require overriding OverrideConfigSection(FString& SectionName) .
Cloud Save Integration
Save Data Encryption
Why encrypt : Prevents casual save editing for competitive/economy sensitive games. Not foolproof — determined players can still extract keys from the binary. Combine with server side validation for authoritative saves.
Step 8: Common Mistakes
Anti Pattern Problem Fix
Saving raw UObject or AActor Pointers invalid between sessions Save FSoftObjectPath or a stable unique ID
No version field Adding/removing fields corrupts old saves silently Always include int32 SaveVersion ; run migrations on load
SaveGameToSlot on game thread per frame Blocks rendering, causes hitches Use AsyncSaveGameToSlot
USTRUCT without GENERATED BODY() in a saved field Silent serialization failure Add GENERATED BODY() to all saved structs
Ignoring Ar.IsError() Reads past corrupted data, applies garbage Check after every block; abort immediately if set
Overlapping async saves Second save starts before first completes Guard with bSaveInProgress flag or IsSaveInProgress()
Hardcoded save file paths Breaks on consoles and different platforms Use UGameplayStatics APIs; FPaths::ProjectSavedDir() only for debug
PIE vs. Packaged / platform paths : In PIE, saves go to <Project /Saved/SaveGames/ . Packaged Windows builds write to %LocalAppData%/<ProjectName /Saved/SaveGames/ . Console platforms use title storage APIs. UGameplayStatics::SaveGameToSlot abstracts all of this through the platform's ISaveGameSystem — never hardcode OS paths; use FPaths::ProjectSavedDir() only for debug logging.
Advanced Edge Cases
Corruption recovery : When Ar.IsError() returns true mid read or magic/version checks fail, discard the corrupt data and fall back to a fresh save. Optionally maintain a backup slot (write to Slot Backup before overwriting Slot Primary ) so players never lose all progress:
Large saves — chunked approach : Split world state across multiple slots by subsystem (e.g., Save World 00 , Save Inventory , Save Quests ). Load each with AsyncLoadGameFromSlot in parallel. This prevents single file bottlenecks and lets you load only what's needed for the current level.
Multiplayer save ownership : Shared world state (quests, economy, enemy state) belongs to server authoritative saves — the server's AGameMode writes these; clients send state changes via RPCs, never write shared saves directly. Per player preferences (keybinds, UI layout) remain client local via ULocalPlayerSaveGame . This split prevents desync and cheating.
Module Dependencies (Build.cs)
Related Skills
ue cpp foundations — UPROPERTY, USTRUCT, UObject lifetime
ue data assets tables — FSoftObjectPath patterns for asset references in saves
ue gameplay framework — GameInstance as save manager host; GameMode auto save integration
Reference Files
references/save system architecture.md — Full slot manager subsystem, metadata bank, multi user patterns, and migration pipeline