Save Systems
Implement cloud-based save systems with versioning and serialization.
Introduction
Save systems persist game progress to the cloud. This guide covers save data structure, versioning, auto-save, and handling save data migrations.
Guide 16 of 25
Screenshot
Step-by-Step Guide
Design save data structure
Define a save object with: player position, health, inventory, quest progress, settings, stats.
Version your save data
Include a version number. When structure changes, increment version and write a migration function.
Implement auto-save
Save at key moments: level complete, checkpoint, every 60 seconds, on game close.
Use async saves
Save asynchronously to avoid frame hitches. Show Saving... indicator while in flight.
Handle save corruption
Validate save data on load. If validation fails, fall back to previous save or start fresh.
Compress large saves
For large data (inventory, world state), compress before storing to reduce cloud costs.
FluxScript Example
Here is a complete FluxScript implementation for this guide:
const SAVE_VERSION = 3
func createSaveData() {
return {
version: SAVE_VERSION,
timestamp: time.now(),
player: { position: player.position, health: player.health, level: player.level },
inventory: inventory.getItems(),
quests: questSystem.getAllStates(),
stats: { playTime: stats.playTime, kills: stats.kills }
}
}
func saveGame() {
data = createSaveData()
ui.show("savingIndicator")
save.set("gameSave", data)
save.flush().then(() => {
ui.hide("savingIndicator")
ui.toast("Game saved")
})
}
func loadGame() {
data = save.get("gameSave")
if data == null { print("New game"); return }
if data.version < SAVE_VERSION {
data = migrateSave(data, data.version)
}
player.health = data.player.health
player.setPosition(data.player.position)
inventory.loadItems(data.inventory)
questSystem.loadStates(data.quests)
}
func migrateSave(data, fromVersion) {
if fromVersion < 2 { data.player.shield = 0 }
if fromVersion < 3 { data.equipment = {} }
data.version = SAVE_VERSION
return data
}
on timer("autoSave", 60) { saveGame() }Node Graph Example
Prefer visual programming? Here is the equivalent Node Graph:
[Function: saveGame] --> [Create Save Data: version, player, inventory]
--> [Show: savingIndicator] --> [Save + Flush async]
--> [Hide indicator] --> [Toast: Game saved]
[Function: loadGame] --> [Save.Get] --> [Branch: null -> new game]
--> [Branch: version < current] --> [Migrate]
--> [Restore: player, inventory, quests, stats]
[Function: migrateSave] --> [If v<2: add shield]
--> [If v<3: add equipment] --> [Update version]
[On Timer "autoSave" 60s] --> [saveGame]Optimization Tips
Keep your implementation fast and efficient with these optimization tips:
- Version your save data from day one. Include a version field and write migration functions when structure changes.
- Save asynchronously. Cloud saves can take 100-500ms — sync saves cause visible frame freezes.
- Compress large save data. Inventories with hundreds of items should be compressed before storage.
- Keep multiple save slots. Store the last 3-5 saves so players can recover from corruption.
Common Mistakes
No save version field
Without a version, updating your game breaks all existing saves. Always include version + migration.
Saving synchronously
Sync saves cause frame freezes. Always use async saves with save.flush().
