Save Data
The SaveData system provides a key-value save system for persisting game data across sessions. It works like Unity's PlayerPrefs: set typed values by string key, save them to a named slot, and load them back later. Supports multiple save slots.
Platform Support
| Platform | Storage Location | Notes |
|---|---|---|
| Windows | ProjectDir/Saves/ |
Filesystem |
| Linux | ProjectDir/Saves/ |
Filesystem |
| Android | ProjectDir/Saves/ |
Internal storage |
| GameCube | Memory Card Slot A | Uses CARD API |
| Wii | SD Card ProjectDir/Saves/ |
Filesystem |
| 3DS | ProjectDir/Saves/ |
Internal storage |
Script Example
Create a Scripts/SaveGameManager.lua:
SaveGameManager = {}
function SaveGameManager:Create()
self.currentSlot = "slot1"
end
function SaveGameManager:Start()
-- Load existing save if available
if SaveData.DoesSaveExist(self.currentSlot) then
SaveData.Load(self.currentSlot)
Log.Debug("Loaded save: " .. self.currentSlot)
Log.Debug(" Player: " .. SaveData.GetString("playerName", "Unknown"))
Log.Debug(" Health: " .. SaveData.GetInt("health", 100))
else
-- Initialize defaults for a new game
SaveData.SetString("playerName", "Hero")
SaveData.SetInt("health", 100)
SaveData.SetFloat("playtime", 0.0)
SaveData.SetVector("spawnPoint", Vec(0, 1, 0))
SaveData.SetBool("tutorialDone", false)
SaveData.Save(self.currentSlot)
Log.Debug("Created new save: " .. self.currentSlot)
end
end
function SaveGameManager:SaveGame()
-- Update playtime before saving
local playtime = SaveData.GetFloat("playtime", 0.0)
SaveData.SetFloat("playtime", playtime + Engine.GetElapsedTime())
-- Save the player's current position
local player = self:GetParent()
if player then
SaveData.SetVector("position", player:GetWorldPosition())
end
SaveData.Save(self.currentSlot)
Log.Debug("Game saved to " .. self.currentSlot)
end
function SaveGameManager:Tick(deltaTime)
-- Save on F5
if Input.IsKeyJustDown(Key.F5) then
self:SaveGame()
end
-- Load on F9
if Input.IsKeyJustDown(Key.F9) then
if SaveData.DoesSaveExist(self.currentSlot) then
SaveData.Load(self.currentSlot)
Log.Debug("Game loaded from " .. self.currentSlot)
end
end
end
Multiple Save Slots
-- Save to different slots
function SaveSlotManager:SaveToSlot(slotNumber)
-- Set up the data you want to save
SaveData.SetInt("health", self.health)
SaveData.SetString("playerName", self.playerName)
SaveData.SetVector("position", self:GetWorldPosition())
SaveData.SetFloat("playtime", self.playtime)
-- Save to the slot
local slotName = "slot" .. tostring(slotNumber)
SaveData.Save(slotName)
end
function SaveSlotManager:LoadFromSlot(slotNumber)
local slotName = "slot" .. tostring(slotNumber)
if SaveData.DoesSaveExist(slotName) then
SaveData.Load(slotName)
self.health = SaveData.GetInt("health", 100)
self.playerName = SaveData.GetString("playerName", "Hero")
self.playtime = SaveData.GetFloat("playtime", 0.0)
local pos = SaveData.GetVector("position", Vec(0, 0, 0))
self:SetWorldPosition(pos)
return true
end
return false
end
-- List available save slots
function SaveSlotManager:GetAvailableSlots()
local slots = {}
for i = 1, 10 do
local slotName = "slot" .. tostring(i)
if SaveData.DoesSaveExist(slotName) then
table.insert(slots, i)
end
end
return slots
end
-- Delete a save slot
function SaveSlotManager:DeleteSlot(slotNumber)
local slotName = "slot" .. tostring(slotNumber)
if SaveData.DoesSaveExist(slotName) then
SaveData.DeleteSave(slotName)
Log.Debug("Deleted save slot " .. tostring(slotNumber))
end
end
Settings / Preferences
SaveData is also useful for player preferences that persist across play sessions:
function SettingsManager:LoadSettings()
if SaveData.DoesSaveExist("settings") then
SaveData.Load("settings")
end
-- Read settings with defaults
self.musicVolume = SaveData.GetFloat("musicVolume", 0.8)
self.sfxVolume = SaveData.GetFloat("sfxVolume", 1.0)
self.difficulty = SaveData.GetInt("difficulty", 1)
self.invertY = SaveData.GetBool("invertY", false)
self.hudColor = SaveData.GetColor("hudColor", Vec(1, 1, 1, 1))
end
function SettingsManager:SaveSettings()
SaveData.SetFloat("musicVolume", self.musicVolume)
SaveData.SetFloat("sfxVolume", self.sfxVolume)
SaveData.SetInt("difficulty", self.difficulty)
SaveData.SetBool("invertY", self.invertY)
SaveData.SetColor("hudColor", self.hudColor)
SaveData.Save("settings")
end
Lua API Reference
See SaveData Lua API for the full function reference.
Things to Know
- In-memory store is global. There is one shared key-value map. Calling
Loadreplaces all current data with the contents of the save file. - Save and Load are separate. Setting values only changes the in-memory data. You must call
SaveData.Save(name)to write to disk. - Type-safe getters.
GetIntonly returns a value if the stored type is Integer. If the key exists but holds a different type, the default is returned. - Default values. All getters accept an optional second argument for the default value. If omitted, sensible defaults are used (0, 0.0, false, "", zero vectors).
- GameCube memory card. On GameCube, saves go to Memory Card Slot A via the CARD API. Call
System.UnmountMemoryCard()when you're done if you need to release the card. - Save slot names are filenames. On filesystem platforms, the slot name becomes the filename in the
Saves/directory. Avoid special characters in slot names.