OneNode Save System
The complete Blueprint save framework for Unreal Engine.
No structs. No boilerplate. No C++. Just nodes that work. Most save systems in Unreal need a custom SaveGame class, a pile of variables, and glue code to read and write every one of them. OneNode replaces all of that with three nodes: pick a slot, store values by name, write to disk. Everything else, from actors and encryption to multiplayer and cloud, builds on those same three ideas.
- Engine support
- Unreal Engine 4.27 to 5.7
- Version
- 2.0
- Backends
- Not applicable
What you get
- Save any value type with a single node
- Save and restore whole Actors, including references and attachments
- Slots, tags, categories, checkpoints and auto-save
- zlib compression plus real AES-256 encryption
- Versioning, migration, backup and corruption recovery
- Multiplayer per-player and world saves, plus cloud sync
- Save Debugger and Setup Wizard editor tools
This is your entire save system
Most save systems in Unreal need a custom SaveGame class, a pile of variables, and glue code to read and write every one of them. OneNode replaces all of that with three nodes you can drop into any Blueprint.
// 1. Point at a save file (a "slot").
Set Active Save Slot (Slot Name = "Player1")
// 2. Store any value under a name you choose.
Save Int (Key = "Coins", Value = 250)
Save Vector (Key = "Spawn", Value = PlayerLocation)
// 3. Write it to disk. Done.
Save All (To Disk)That is a real, working save. Reloading is the mirror image: Load All (From Disk), then Load Int ("Coins"). No SaveGame class, no boilerplate, nothing to wire up in advance.
Why not just build it yourself?
You can. Here is what that actually costs you, versus what OneNode does out of the box.
| Task | Build it yourself | With OneNode |
|---|---|---|
| Save an integer | SaveGame class, variable, cast, save-to-slot code | One Save Int node |
| Save a whole actor transform | Manually copy each property, rebuild on load | One Save Actor node |
| Keep actor references after load | Store IDs, re-find every actor, relink by hand | Restore Actor References |
| Compress and encrypt the file | Write zlib and AES yourself, manage the key | Tick two settings |
| Auto-save every N seconds | Timers, flush logic, threading | Enable Auto Save |
| Load an old save after a patch | Version checks and hand-written migration | Register Migration Step |
| Per-player saves in multiplayer | Resolve net IDs, per-player files, server auth | Save Player (built in) |
The build-it-yourself column is where days disappear, and where the hard-to-find bugs live: lost references, corrupted files, saves that break on your next patch. OneNode ships all of it, tested across UE 4.27 through 5.7.
OneNode does not lock you in. Under the hood it is a normal Unreal SaveGame written to your project Saved/SaveGames folder. You can walk away any time, because your saves are standard files.
Who it is for
Anyone building in Unreal with Blueprint who needs saving that just works: solo devs, small teams, game jams, and shipped commercial titles. If you have ever lost an afternoon to a SaveGame class, this is for you.
Install it
- 01Buy it on Fab. Once purchased, OneNode lives in your Fab Library permanently, and every future engine-version update is a free re-download.
- 02Install it to your engine. Open the Epic Games Launcher, go to Fab Library, find OneNode Save System, click Install to Engine, and choose your engine version (4.27 or 5.0 to 5.7).
- 03Enable it in your project. Open your project, then Edit > Plugins. Search OneNode, tick Enabled, and click Restart Now when Unreal asks. That is the only project setup step.
- 04Confirm it works. Open any Blueprint graph, right-click, and type Save Int. If the node appears under the OneNode Save System category, you are ready to save.
Prefer a manual install?
// 1. Unzip the folder that matches your engine, e.g. UE5.3.
// 2. Copy the "OneNodeSaveSystem" folder into:
YourProject/Plugins/OneNodeSaveSystem
// (create the "Plugins" folder if it does not exist)
// 3. Reopen the project. Enable it under Edit > Plugins.Always use the zip that matches your engine version. A UE 5.3 build will not load in 5.7 and vice versa. The version is in the file name, for example OneNodeSaveSystem_UE5.3.zip.
Your first save in 5 minutes
Let us save a value and read it back. Do this in your Player Character or Game Instance, anywhere with a Blueprint graph.
Step 1: choose a slot
A slot is one save file. Give it a name. Do this once, early, for example on BeginPlay or when the player starts a new game.
Set Active Save Slot (Slot Name = "SaveGame01")Step 2: save some values
Save Int (Key = "Coins", Value = 250)
Save String (Key = "Name", Value = "Aria")
Save Vector (Key = "Spawn", Value = GetActorLocation)
// Nothing is on disk until you flush:
Save All (To Disk)Step 3: load it back
Set Active Save Slot (Slot Name = "SaveGame01")
Load All (From Disk)
Coins = Load Int (Key = "Coins", Default = 0)
Name = Load String (Key = "Name", Default = "Player")
Spawn = Load Vector (Key = "Spawn", Default = 0,0,0)Every Load node takes a Default value. If the key was never saved, say in a brand-new game, you get the default instead of a crash or an empty value. That single habit prevents most save-related bugs.
That is a complete, shippable save loop. Everything from here just adds capability on top of these same nodes.
Saving values
OneNode has a dedicated Save node for every common Blueprint type. Each takes a Key, the name you will load it by, and a Value. Call Save All (To Disk) when you are ready to write.
| Type | Node | Type | Node |
|---|---|---|---|
| Integer | Save Int | Vector | Save Vector |
| Integer64 | Save Int64 | Rotator | Save Rotator |
| Float | Save Float | Transform | Save Transform |
| Boolean | Save Bool | Color | Save Color |
| Byte | Save Byte | Name | Save Name |
| String | Save String | Raw bytes | Save Raw Bytes |
Arrays
Whole arrays save in one node too, with no looping. Supported array nodes: Save Int Array, Save Float Array, Save String Array, Save Name Array, Save Vector Array and Save Transform Array.
Save String Array (Key = "Inventory", Value = InventoryItems)
Save Int Array (Key = "Quantities", Value = ItemCounts)
Save All (To Disk)Keys are just text and are case-sensitive. "Coins" and "coins" are two different values. Pick a convention and stick to it.
Useful companions
Has Save Key tells you whether a key exists before you read it. Remove Key deletes one value. Get All Keys returns every key in the slot, handy for debugging. Get Entry Count gives you the total.
Loading values
Loading mirrors saving. Read the file once with Load All (From Disk), then pull each value with its matching Load node and key.
Load All (From Disk)
Health = Load Float (Key = "Health", Default = 100.0)
Level = Load Int (Key = "Level", Default = 1)
Alive = Load Bool (Key = "Alive", Default = true)The Default is your safety net
If a key is missing, whether a fresh game or a save from before you added that feature, the Load node returns your Default instead of failing. This is the single most important habit in the whole system: always give a sensible default.
Want to branch on whether a save even exists? Use Save Slot Exists (Slot Name) before loading. Show Continue only when it returns true, and New Game otherwise.
Checking before you read
Load All (From Disk)
Branch on: Has Save Key ("TutorialDone")
// True -> skip the tutorial
// False -> play the tutorial, then Save Bool("TutorialDone", true)Saving structs and raw bytes
Your own data types save too. Two approaches, depending on how tidy you want the save file.
Option A: save the fields
Break your struct and save each field under a clear key. Verbose, but the save file is human-readable and easy to migrate later.
// Break "PlayerStats" -> Health, Stamina, Level
Save Float ("Stats.Health", Health)
Save Float ("Stats.Stamina", Stamina)
Save Int ("Stats.Level", Level)Option B: save raw bytes
Serialise any struct to a byte array and store it in one node with Save Raw Bytes. Compact and fast, ideal for large or deeply-nested data where you do not need to read individual fields.
// Convert your struct to bytes, then store the whole blob:
Save Raw Bytes (Key = "SaveBlob", Value = StructBytes)
// Read it back and rebuild the struct:
Bytes = Load Raw Bytes (Key = "SaveBlob")Prefer Option A while your data is still changing, since named fields are trivial to migrate when you add or rename something. Reach for raw bytes once a struct is stable and you care about file size.
Saving actors
Instead of saving properties one by one, save an entire actor, its transform and its marked variables, in a single node.
Mark what to save
On the actor variables you want persisted, tick SaveGame in the variable Details panel, under Advanced > SaveGame. OneNode saves exactly those.
Save Actor (Actor = self, Key = "Chest_01")
Save All (To Disk)
// ...later / next session:
Load All (From Disk)
Load Actor (Actor = self, Key = "Chest_01")Many actors at once
Save Multiple Actors takes an array. Save Actors With Tag saves everything carrying a gameplay tag, so one node persists every door, pickup or enemy in a level. Load Actors By Save Tag brings them all back.
Save Actors With Tag (Tag = "Persistent")
Save All (To Disk)
// Reload the whole set later:
Load Actors By Save Tag (Tag = "Persistent")Use Has Actor Save Data (Key) to check whether an actor was ever saved, and Get Saved Actor Count for totals. Get All Actor Keys lists them, useful when spawning actors back from a save.
Actor references and attachments
The classic save bug: you reload, and every actor-to-actor pointer is null. OneNode fixes this for you.
The problem
If an actor stores a reference to another actor, such as a weapon pointing at its owner or an enemy at its patrol node, a naive save writes a memory address that means nothing next session. On load, the pointer is null and things break.
The fix, one node
OneNode records references as stable markers at save time. After you have loaded and respawned your actors, call Restore Actor References once. It walks every saved actor and reconnects the pointers, including attachment parents and sockets, so a sword stays in the hand it was attached to.
Load All (From Disk)
Load Actors By Save Tag ("Persistent") // respawn the actors
// Now relink every reference and re-attach children:
Restore Actor ReferencesCall Restore Actor References after all the actors it needs to point at exist in the world. If a target has not been spawned yet, that one link is skipped and the rest still restore. So load your actors first, then restore references last.
Any reference marked SaveGame is handled: single actor references, arrays of references, and the actor attachment chain. No IDs to manage, no re-finding by name.
Save categories
Categories let one system separate the kinds of data a game keeps, so the right things live in the right file with the right lifetime.
| Category | Use it for |
|---|---|
| Global | Settings, achievements, unlocks. Shared across every save. |
| Player | Progress, inventory, skills. Tied to one player. |
| World | Doors, chests, NPC states. The state of a level. |
| Checkpoint | Temporary progress since the last checkpoint. |
| Session | Multiplayer runtime data for the current session. |
| Profile | A named player profile. |
Set Active Category (Global)
Save Bool ("Ach_FirstBlood", true) // shared across all saves
Set Active Category (Player) // this player only
Save Int ("Coins", 250)
Save All (To Disk)A common split: keep audio and graphics settings and achievements in Global so they persist no matter which save the player loads, and keep run-specific progress in Player or World.
Async, auto-save and checkpoints
Big saves should not freeze the game, and players should not lose progress. These features cover both.
Async (non-blocking) saves
Save All Async (Non-Blocking) writes on a background thread and fires an event when it is done, with no hitch even for large saves. Load All Async does the same for loading. Use these for autosaves during gameplay.
Save All Async (Non-Blocking)
// -> bind "On Save Completed" to show a "Saved" iconAuto-save
Enable Auto Save (Interval = 300.0)
// Force one right now, e.g. before a boss fight:
Trigger Auto SaveEnable Auto Save takes an interval in seconds and saves on a timer for you. Disable Auto Save stops it, and Trigger Auto Save forces one immediately, for example on level exit.
Checkpoints
Checkpoint Save writes a temporary progress snapshot the player returns to on death, separate from their manual saves, so a checkpoint never overwrites a real save file.
Pair Force Save Flush with app shutdown, or use Has Unsaved Changes, to guarantee nothing is lost when the player quits mid-session.
Events
React to what the save system is doing: show a spinner, pop a "Saved" toast, or handle a corrupt file gracefully. Bindable events fire at each stage of a save or load, so your UI and game logic can respond without polling.
- On Save Started / Completed: show and hide a saving indicator.
- On Load Completed: fade in the world once data is ready.
- On Auto Save: flash a subtle "Autosaved" toast.
- On Save Corrupted: fall back to a backup instead of crashing.
Polling helpers
When you would rather ask than subscribe: Is Saving, Is Loading, Is Save Manager Ready and Has Unsaved Changes each return a bool you can branch on in Tick or on a button press.
Guard your save button with Is Saving so a player cannot queue ten saves by mashing it. Grey the button out while a save is in flight, and re-enable it on On Save Completed.
Compression and encryption
Make saves smaller and tamper-proof. Both are off by default and toggle with a single node, and existing saves keep loading either way.
Compression (zlib)
Set Compression Enabled (true) shrinks saves with zlib, often dramatically for large or repetitive data. Check the current state with Is Compression Enabled.
Encryption (AES-256)
Enable AES Encryption with your key encrypts the save with real AES-256, so players cannot open or edit the file in a text editor. Disable AES Encryption turns it off, and Is AES Encryption Enabled reports the state.
Set Compression Enabled (true)
Enable AES Encryption (Key = "your-secret-key")
Save All (To Disk) // now compressed and encryptedKeep your AES key consistent across a build. If the key changes, older saves made with the previous key cannot be decrypted and you get an Encryption Key Mismatch result. Store the key somewhere stable in your project, not hard-coded in a throwaway variable.
Saves made without these features still load after you enable them. OneNode detects an unprotected file and reads it directly, so you can turn compression or encryption on mid-project without breaking existing saves.
Versioning and migration
The feature that saves you after launch: load a player old save even though your data changed in a patch.
The problem
You ship. Players build up saves. In patch 1.1 you rename "HP" to "Health" and add a new stat. Without migration, every existing save is now subtly wrong or broken.
The fix: register migration steps
Stamp your save format with Set Save Version. When you change the format, register a step describing how to upgrade from the old version to the new one. On load, OneNode runs any needed steps automatically.
Set Save Version (2)
Register Migration Step (From = 1, To = 2)
// inside: read old "HP" -> write new "Health", set defaults
// On load, OneNode checks the file version and upgrades it:
Load All (From Disk) // v1 saves are migrated to v2 for youHelpers: Get Current Save Version, Save Needs Migration, Run Migrations and Get Save Version Description let you inspect and control the process. Clear Registered Migrations resets them, which is useful in tests.
Register your migration steps once at startup, in Game Instance Init. Then you never think about it again, because old saves quietly upgrade themselves the moment a returning player loads them.
Backup and recovery
Disks fill up, power cuts out, files corrupt. OneNode keeps backups so a bad write does not cost the player their game.
Before overwriting a slot, OneNode can keep the previous version as a backup. Set Backup Retention (count) controls how many are kept, and Has Backup checks whether one exists. If a save reports Save File Corrupted, call Restore Backup to roll the slot back to the last good copy, then tell the player you recovered their progress.
Set Backup Retention (Count = 3) // keep last 3 saves
// On load, if the result is "Save File Corrupted":
Branch: Has Backup
True -> Restore Backup -> Load All (From Disk)
False -> start a new game, warn the playerBackups cost a little disk space, and that is the trade for never losing a player save to a single bad write. For most games, a retention of 2 to 3 is plenty.
Multiplayer saves
Saving in multiplayer means two things: each player own progress, and the shared state of the world. OneNode handles both, with server authority built in.
Per-player saves
Save Player and Load Player take a Player Controller and store that player data in their own file. OneNode resolves a stable player identity for you with Resolve Player Id from the net ID, so the right save follows the right player across sessions.
Save Player (Controller = PC) // filed under that player id
// Next session, same player:
Load Player (Controller = PC)World saves (server only)
Save World (Server Only) and Load World persist shared level state. They are guarded by authority: Is Network Authority gates the write so only the server can save the world, and a client call returns Not Network Authority instead of corrupting shared state.
OneNode includes a replicated save component that transfers a client save data to the server in verified, paced chunks, so large saves move safely across the network without stalling the game. You drive it through the same Save Player and Load Player nodes.
Helpers: Is Dedicated Server and Is Network Client let you branch your save logic by role when you need to.
Cloud saves
Sync saves to Steam Cloud, Dropbox, or your own backend through one simple provider interface. Point it at a provider and your saves sync up and down. A local-folder provider ships in the box for testing, and the interface is designed so a Steam or Dropbox provider drops in the same way.
Conflict handling
When local and cloud saves disagree, you choose the winner: Prefer Cloud downloads, Prefer Local uploads. No silent data loss, because the resolution is always your call.
// Set your provider once, then sync:
Sync Saves (Conflict = Prefer Cloud) // pull newest from cloud
// ...at quit:
Sync Saves (Conflict = Prefer Local) // push local upDuring this project live test sweep, the Steam Cloud path reported 2 of 4 sub-checks failing, because that path needs a real Steam app context to fully validate. The provider interface and local sync are solid. Treat a specific storefront provider as something to verify in your own build with your app credentials.
Editor tools
Save Debugger
Open the Save Debugger to inspect any slot live: every key, its type and value, tags, categories, version and file size. From Blueprint, Debug: Dump All Save Data, Get Save Debug Lines and Get Save Debug Summary print the same information to log or UI.
Debug: Dump All Save Data // prints every key/value to the log
Summary = Get Save Debug Summary // one-line overview for UISetup Wizard
The Setup Wizard walks you through first-time configuration, covering default slot, compression, encryption and backup retention, and writes the settings for you, so you are saving correctly from minute one.
When a save behaves unexpectedly, open the Save Debugger before anything else. Nine times out of ten you spot the problem instantly: a mistyped key, a value in the wrong category, or an older save version than you expected.
Analytics and profile metadata
Rich metadata turns a bare save slot into a proper save card, and gives you numbers about how your game is played.
Profile metadata
Set Player Name ("Aria")
Set Level Name ("The Drowned City")
Set Progress Description ("Chapter 3 - 62%")
Add Play Time (DeltaSeconds)
Set Screenshot From PNG (ScreenshotBytes)Read it all back with Get Profile Metadata so your load screen can show it.
Analytics
Get Save Analytics returns aggregate figures such as totals, sizes and counts, and Set Custom Metadata Field lets you attach your own key/value stats to a save. Useful for balancing, QA or a stats screen.
Add Play Time called each session gives you an accurate total playtime per slot for free, a detail players notice on a polished load screen.
Recipes
A working Save / Load menu
// SAVE button:
Set Active Save Slot (SelectedSlotName)
Set Level Name (Current Level) ; Add Play Time (Session)
Save All Async (Non-Blocking) -> toast "Saved"
// LOAD screen build:
Slots = Get All Slot Infos -> one UI card per entry
// LOAD button:
Set Active Save Slot (SelectedSlotName) ; Load All (From Disk)Checkpoint and respawn
// Reaching a checkpoint:
Save Actor (Player, "Player") ; Checkpoint Save
// On death:
Load All (From Disk) ; Load Actor (Player, "Player")
Restore Actor ReferencesSecure release build
Set Compression Enabled (true)
Enable AES Encryption (BuildKey)
Set Backup Retention (3)Troubleshooting
| Symptom | Cause and fix |
|---|---|
| Load returns nothing or defaults | No slot set, or the wrong slot name. Call Set Active Save Slot with the exact name, then Load All (From Disk) before reading. |
| Values are empty after load | You read before loading. Load All (From Disk) must run before any Load node. |
| Actor references are null | Call Restore Actor References after the target actors are spawned, not before. |
| Actor properties not saved | Tick SaveGame on each variable, under Details > Advanced, so OneNode knows to persist it. |
| Encryption Key Mismatch | The AES key changed between save and load. Use one stable key per build. |
| Save File Corrupted | Check Has Backup, then Restore Backup. Set backup retention so this never costs progress. |
| Nodes do not appear | The plugin is not enabled for this project. Edit > Plugins, enable OneNode, restart. |
| Old saves broke after a patch | Add Register Migration Step from the old version to the new. |
Node reference
Every node, grouped by job. All live under the OneNode Save System category in the Blueprint right-click menu.
| Group | Nodes |
|---|---|
| Slots | Set Active Save Slot, Get Active Slot Name, Save Slot Exists, Delete Save Slot, Copy Slot, Rename Slot, Get All Slot Names, Get All Slot Infos, Get Slot Info, Sanitize Slot Name |
| Save values | Save Int, Save Int64, Save Float, Save Bool, Save Byte, Save String, Save Name, Save Vector, Save Rotator, Save Transform, Save Color, Save Raw Bytes |
| Save arrays | Save Int Array, Save Float Array, Save String Array, Save Name Array, Save Vector Array, Save Transform Array |
| Load values | Load Int, Load Int64, Load Float, Load Bool, Load Byte, Load String, Load Name, Load Vector, Load Rotator, Load Transform, Load Color, Load Raw Bytes |
| Load arrays | Load Int Array, Load Float Array, Load String Array, Load Name Array, Load Vector Array, Load Transform Array |
| Keys and data | Has Save Key, Remove Key, Get All Keys, Get Entry Count, Clear All Data, Clear Memory Cache |
| Disk I/O | Save All (To Disk), Load All (From Disk), Save All Async (Non-Blocking), Load All Async (Non-Blocking), Quick Save, Quick Load, Force Save Flush, Has Unsaved Changes, Save Slot To File, Load Slot From File, Export Slot To Bytes, Import Slot From Bytes |
| Actors | Save Actor, Load Actor, Save Multiple Actors, Save Actors With Tag, Load Actors By Save Tag, Restore Actor References, Has Actor Save Data, Get Saved Actor Count, Get All Actor Keys |
| Tags | Save By Tag, Load By Tag, Delete By Tag, Remove All By Tag, Get All Tags, Has Tag, Get Keys By Tag, Remove Multiple Tags |
| Categories | Set Active Category, Get Save Scope, Set Save Scope, Save Category, Load Category |
| Auto-save and checkpoints | Enable Auto Save, Disable Auto Save, Trigger Auto Save, Checkpoint Save |
| Security | Set Compression Enabled, Is Compression Enabled, Enable AES Encryption, Disable AES Encryption, Is AES Encryption Enabled, Enable Encryption, Disable Encryption, Is Encryption Enabled |
| Versioning | Set Save Version, Get Current Save Version, Get Save Version Description, Save Needs Migration, Register Migration Step, Run Migrations, Clear Registered Migrations, Get Plugin Save Version |
| Backup | Set Backup Retention, Has Backup, Restore Backup |
| Multiplayer | Save Player, Load Player, Save World (Server Only), Load World, Resolve Player Id, Is Network Authority, Is Dedicated Server, Is Network Client |
| Cloud | Sync Saves, Prefer Cloud (download), Prefer Local (upload) |
| Metadata and analytics | Get Profile Metadata, Set Player Name, Set Level Name, Set Progress Description, Add Play Time, Set Screenshot From PNG, Set Custom Metadata Field, Get Save Analytics, Get Save File Size On Disk, Get Save Size (Bytes) |
| Debug and status | Debug: Dump All Save Data, Get Save Debug Lines, Get Save Debug Summary, Is Saving, Is Loading, Is Save Manager Ready, Save Result To String, Save Result Is Success |
Stuck on something?
We answer every serious message ourselves. Discord is the fastest way to get an answer from the person who built the plugin.