Save and Load
This guide covers how to persist placed objects across game sessions using the Grid Building plugin’s built-in save/load API.
Version note: This guide is validated for Grid Building 5.0.5.
Core Concepts
Persistence relies on two plugin-provided elements:
PlaceableInstance: A component attached to every valid placement. It holds the “DNA” of the object (template reference, transform) and provides the save/load methods.PlaceableInstancegroup: EveryPlaceableInstanceautomatically joins this Godot group on creation. This is the canonical way to discover all placed objects in the scene.
Note: The plugin does not provide a file I/O system, world state manager, or player-state serializer. Those are game-specific concerns you implement yourself (see Demo Reference for an example).
Discovering Placed Objects
The plugin tracks placed objects through the "PlaceableInstance" Godot group. Every time the building system places an object, it attaches a PlaceableInstance node that auto-registers itself:
| |
Why groups instead of a central list?
- Reliable:
PlaceableInstance._init()callsadd_to_group(group_name)automatically. - Validated:
PlaceableInstance.validate_setup()warns if a node is missing the group. - Zero maintenance: You never need to manually register or unregister objects; Godot handles group membership with the node’s lifetime.
- No central tracker:
BuildingStateand other plugin systems do not maintain a separateplaced_objectsarray. The group is the source of truth.
Saving
Step 1: Collect data from placed objects
Iterate the PlaceableInstance group and call save() on each node:
| |
What PlaceableInstance.save() returns
The returned Dictionary uses these exact keys (defined in PlaceableInstance.Names):
| Key | Value | Constant |
|–|-|******-|
| "instance_name" | The placed object’s node name | PlaceableInstance.Names.INSTANCE_NAME |
| "transform" | var_to_str(parent.transform) | PlaceableInstance.Names.TRANSFORM |
| "placeable" | Load data for the Placeable resource | PlaceableInstance.Names.PLACEABLE |
Do not invent your own keys. If you need extra data (durability, owner ID, etc.), store it in a separate dictionary and merge it after calling
save(). Changing the built-in keys will breakinstance_from_save().
Loading
Step 1: Clear existing placed objects
| |
Step 2: Rebuild from save data
| |
What PlaceableInstance.instance_from_save() does
- Loads the
Placeableresource from the saved reference. - Instantiates the resource’s
packed_scene. - Adds it to
p_instance_parent. - Restores
nameandtransformfrom the save entry. - Attaches a fresh
PlaceableInstancecomponent (only if the scene root doesn’t already have one).
Adding Custom Save Data
If your placed objects have game-specific state (health, inventory, rotation), merge it after calling the plugin’s save():
| |
On load, restore custom data after instance_from_save() returns:
| |
Edge Cases
- Missing resources: If a
placeableresource path no longer exists,Placeable.load_resource()returns null andinstance_from_save()emits an error. Always check for null returns. - UID resolution:
Placeable.load_resource()supports UID resolution in web builds (5.0.4+). - Schema changes: The plugin does not provide a migration system. If you change your custom data structure, handle version checking in your own save wrapper.
- Previews and ghosts: Objects marked with
"gb_preview"metadata are transient and should be skipped during save. The plugin’s demo scenes use this convention; adopt it in your own preview system if you want the same filtering behavior.
Demo Reference
The plugin ships with a fully worked save/load example in the demo scenes. These classes are not part of the addon API — they show one possible way to wire the plugin’s save/load into a complete game.
| Demo Class | Purpose | Location |
|||***|
| DemoSaveLoad | JSON file I/O, folder creation, error handling | demos/shared/save/demo_save_load.gd |
| WorldState | Multi-level world persistence, level switching | demos/shared/world/world_state.gd |
| Level | Per-level save/load, PlaceableInstance group iteration | demos/shared/world/level.gd |
| LevelState | Resource-based save data container | demos/shared/save/level_state.gd |
| PlayerState | Player position, inventory, etc. | demos/shared/save/player_state.gd |
How the demo layers on top of the plugin
| |
Use the demo as a starting point, but remember: PlaceableInstance.save() and PlaceableInstance.instance_from_save() are the only plugin APIs you must call. Everything else (JSON, LevelState, WorldState, player data) is your own architecture.