menu_bookDocumentation
Sandbox: SaveSystem — scene diff save/load with versioning and ISaveEvents
Sandbox SaveSystem — Scene Diff Save/Load
The SaveSystem captures the difference between the current scene state and the original scene file. This means saves are compact — only changed/added/removed objects are stored.
Save format
JSON
{
"Version": 2,
"Metadata": { "key": "value" },
"Packages": ["org.package1", "org.package2"],
"SceneProperties": { ... },
"Objects": [ ... diff object definitions ... ]
}Key API
CSHARP
public sealed class SaveSystem : GameObjectSystem<SaveSystem>, ISceneLoadingEvents
{
public static int SaveVersion => 2;
public string LoadedSavePath { get; private set; }
public bool HasLoadedSave => LoadedSavePath is not null;
// Save current scene state to a file
public async Task<bool> Save( string path ) { ... }
// Load a save file — host only
public async Task<bool> Load( string path ) { ... }
// Metadata API
public void SetMetadata( string key, string value ) { ... }
public string GetMetadata( string key, string defaultValue = null ) { ... }
public IReadOnlyDictionary<string, string> GetAllMetadata() { ... }
// Read metadata without loading the full save
public static IReadOnlyDictionary<string, string> GetFileMetadata( string path ) { ... }
// Read save version without loading
public static int GetFileSaveVersion( string path ) { ... }
}Load flow
- Read the save JSON and extract the diff
- Mount any required packages listed in the save
- Broadcast a loading screen to all clients
- Set _suppressSystemScene = true to prevent duplicate system scenes
- Call CleanupSystem.PreserveBaselineForSaveLoad()
- Build a patched scene file from the diff and call Game.ChangeScene()
ISaveEvents
CSHARP
public interface ISaveEvents
{
void BeforeSave( string filename ) { }
void AfterSave( string filename ) { }
void BeforeLoad( string filename ) { }
void AfterLoad( string filename ) { }
}Implement Global.ISaveEvents on a GameObjectSystem or Component to hook into save/load lifecycle. The GameManager uses AfterLoad to re-spawn any players not included in the save.
Gotchas
- Save version 2 saves are incompatible with version 1 — check GetFileSaveVersion before loading
- _suppressSystemScene prevents the system scene from loading twice when a save is loaded on top of an existing scene
- CleanupSystem.PreserveBaselineForSaveLoad() must be called before Game.ChangeScene() to correctly restore baseline objects
- Only the host can call Load() — clients receive the new scene via normal networking
Was this helpful?