A slot-based save and load system for Godot 4 with persistent world objects: picked-up items stay picked up, opened chests stay open, and the player comes back exactly where they saved.
Features
- Save slots with a folder per slot:
state.jsonfor the game data andmeta.jsonfor what a save menu lists (time saved, a summary line, version). - Atomic writes. Each file is written to a
.tmpfile first and then renamed, so a crash mid-save cannot corrupt a slot. - The
persistgroup pattern. Any node in thepersistgroup withsave_to_state(state)andload_from_state(state)is saved and loaded for you. No central list of what to save. - Removed objects. Call
SaveManager.mark_removed(self)before freeing a collected item or a killed enemy and it stays gone after loading. - Load mid-game, correctly.
reload_and_load_current_slot()reloads the scene first, so an item you picked up after saving comes back. - Versioned saves with a
_migrate()hook for upgrading old save files after you change the format. - Errors you can handle:
save_slot()returns anError,load_slot()returns{ok, err, state}, andsave_failedandload_failedsignals fire on any failure, including a corrupt file. - Slot helpers:
has_save(),get_slot_info(),list_slots()(newest first) anddelete_slot(). SaveUtilsfor the types JSON cannot hold:Vector2andVector3to and from dictionaries.
Requirements
- Godot 4.7 or later, standard build (GDScript only, no .NET needed).
- Tested on Godot 4.7.2 stable on Windows. Earlier 4.x versions are untested.
reload_and_load_current_slot()usesSceneTree.scene_changed, which needs Godot 4.5 or later. - Uses the Compatibility renderer, so it runs on older GPUs too.
Quick Start
- Press F5.
- Move with WASD or the arrow keys and collect a couple of potions.
- Press E next to the chest to open it.
- Click Save on Slot 1.
- Collect more potions, then click Load on Slot 1.
Saves are written to user://saves. In the editor, Project > Open User Data
Folder shows you the JSON.
Known Limitations
- Persistent ids are scene paths. Give persistent nodes unique names and keep them under the same parent, or their saved state will not find them.
- Nodes spawned at runtime (dropped loot, spawned enemies) are not recreated on
load. Save them as data in a parent node's
save_to_state()and respawn them inload_from_state(). removed_nodeslives in the autoload. Clear it (SaveManager.removed_nodes.clear()) when the player starts a new game.- Saves are plain JSON, so players can read and edit them. Encrypt or sign them if that matters for your game.
- One scene at a time: the save covers whatever is in the current scene tree.
- Tested on Godot 4.7.2 on Windows only.
License
MIT for the code. See LICENSE.
Third-Party Assets
The knight, chest and potion sprites are from
Tiny Dungeon by Kenney, released under
CC0 1.0. Details in THIRD_PARTY_ASSETS.md, and the pack's
original license is in assets/kenney_tiny-dungeon/License.txt.
Learn How It Works
Want to understand how this works instead of just copying it?
CodingQuests teaches you how to build systems like this step by step in Godot, with interactive lessons and real projects.
- Save + Load System builds this save system lesson by lesson: slots, atomic writes, the persist group pattern and versioning. The first 4 lessons are free.
Source code, integration instructions and issue tracker: https://github.com/CodingQuests/godot-save-system
Changelog for version 1.0.0
2026-10-17 01:28:24
No changelog provided for this version.