GDevelop provides two main ways to save game data:
1. Storage Actions (Local Storage) — Persistent Between Sessions
This is the most common way to save progress. Data is stored on the user’s device (browser, desktop, mobile).
What you can save
- Player position
- Inventory
- Level progression
- Settings (sound, graphics)
- Anything that fits into variables
How to Save Data
Use the action:
📌 Storage → Write a value to storage
Example: Save current level
Write GlobalVariable(CurrentLevel)
in storage "SaveData"
at key "level"
How to Load Data
Use the action:
📌 Storage → Read a value from storage
Example: Load saved level into a variable
Read value from key "level" in storage "SaveData"
and store it in GlobalVariable(CurrentLevel)
Important:
After reading, you must check if the value exists.
2. JSON Save/Load (Useful for large data or structured saves)
You can serialize (convert) variables into JSON and save them as text.
Saving
Do = ToJSONStructure(GlobalVariable(PlayerData)) to GlobalVariable(SaveJSON)
Write GlobalVariable(SaveJSON) in storage "SaveData" at key "PlayerData"
Loading
Read "PlayerData" from storage "SaveData" into GlobalVariable(TempJSON)
Deserialize JSON string GlobalVariable(TempJSON) into GlobalVariable(PlayerData)
⭐ Recommended Variable Structure for Saves
Global Structure
PlayerData
Level = 2
Health = 90
Coins = 350
Inventory
Sword = true
Shield = false
PotionCount = 3
⭐ Auto-Save Example (common in platformers/RPGs)
Event
Condition:
Player collides with SavePoint
Actions:
Write GlobalVariable(PlayerData) to storage "SaveData" at key "PlayerData"
Play sound "save.wav"
⭐ Loading Game Example (on start of scene)
Event
At the beginning of the scene:
Read "PlayerData" from storage "SaveData" into GlobalVariable(Temp)
If GlobalVariable(Temp) != "" :
Deserialize JSON to GlobalVariable(PlayerData)
Create player at PlayerData.X ; PlayerData.Y
Set coins to PlayerData.Coins
🔥 Bonus: Autosave vs Manual Save
Manual Save Trigger
Player presses a button (“Save Game”):
When key S is pressed:
Write save data...
Autosave Trigger
Every 10 seconds:
Write save data...
⭐ Full Example File?
✅ A complete GDevelop save/load event sheet
✅ Example with structured variables
✅ A minimal project template you can paste into GDevelop
Below is a ready-to-use GDevelop example project (JSON) containing:
✅ Global variables with structured save data
✅ Save + Load events
✅ Simple player object with position saving
✅ Works in GDevelop 5+ (copy → paste into a new project’s game.json)
📦 GDevelop Example Save/Load System (game.json snippet)
👉 How to use:
- Create a new empty project in GDevelop
- Open the
game.json(right-click project → edit as JSON) - Replace the file with the version below OR merge the parts you need
- Save & reopen GDevelop
📁 Complete Example File
{
"firstLayout": "Level1",
"properties": {
"windowWidth": 1280,
"windowHeight": 720,
"adaptGameResolutionAtRuntime": true
},
"objects": [
{
"name": "Player",
"type": "Sprite",
"animations": [
{
"name": "idle",
"direction": 0,
"spriteSize": { "width": 32, "height": 32 },
"images": [ "player.png" ]
}
]
}
],
"layouts": [
{
"name": "Level1",
"objectsInstances": [
{
"name": "Player",
"x": 100,
"y": 100
}
],
"events": [
{
"type": "BuiltinCommonInstructions::Standard",
"conditions": [
{ "type": "BuiltinCommonInstructions::AtTheBeginning" }
],
"actions": [
{
"type": "Storage::ReadStringFromJSON",
"parameters": [ "SaveData", "SaveJSON", "TempSave" ]
},
{
"type": "CommonInstructions::JsCode",
"parameters": [
"if (runtimeScene.getVariables().get(\"TempSave\").getAsString() !== \"\") {\n" +
" const json = runtimeScene.getVariables().get(\"TempSave\").getAsString();\n" +
" runtimeScene.getVariables().get(\"SaveStruct\").fromJSON(json);\n" +
" const p = runtimeScene.getInstancesOf(\"Player\")[0];\n" +
" p.setX(runtimeScene.getVariables().get(\"SaveStruct\").getChild(\"PlayerX\").getAsNumber());\n" +
" p.setY(runtimeScene.getVariables().get(\"SaveStruct\").getChild(\"PlayerY\").getAsNumber());\n" +
"}"
]
}
]
},
{
"type": "BuiltinCommonInstructions::Standard",
"conditions": [
{
"type": "BuiltinCommonInstructions::KeyPressed",
"parameters": [ "S" ]
}
],
"actions": [
{
"type": "CommonInstructions::JsCode",
"parameters": [
"const p = runtimeScene.getInstancesOf(\"Player\")[0];\n" +
"const saveVar = runtimeScene.getVariables().get(\"SaveStruct\");\n" +
"saveVar.getChild(\"PlayerX\").setNumber(p.getX());\n" +
"saveVar.getChild(\"PlayerY\").setNumber(p.getY());\n" +
"runtimeScene.getVariables().get(\"SaveJSON\").setString(saveVar.toJSON());"
]
},
{
"type": "Storage::WriteJSONToString",
"parameters": [ "SaveData", "SaveJSON", "SaveJSON" ]
}
]
}
]
}
],
"variables": [
{
"name": "SaveStruct",
"type": "structure",
"value": {
"PlayerX": 100,
"PlayerY": 100
}
},
{ "name": "SaveJSON", "type": "string", "value": "" },
{ "name": "TempSave", "type": "string", "value": "" }
]
}
🧾 Features in this example
✔ Loads player position at scene start
If save exists → load X/Y from storage.
✔ Press S to save
Saves:
- PlayerX
- PlayerY
✔ Uses a structured global variable SaveStruct
✔ JSON-safe & compatible with export builds
🎁 Want a more complete file?
I can generate:
🔧 Version with:
- Multiple scenes
- Inventory saving
- Level progression
- Autosave
- Save slots
- Cloud sync (Firebase)
Email at contact@tastycherrygames.com
