Game Data & Balancing
The Game Data editor is a spreadsheet interface for managing game balance. Create tables for XP curves, item stats, difficulty parameters, and more—then compare changes across versions.
Why Live Balancing?
Section titled “Why Live Balancing?”Without Quest Data, a balance change means: edit code → rebuild → distribute build → testers wait. With Live Balancing, a designer edits a cell in the dashboard and the running game updates in under a second.
3 SDK calls. ~75 bindings. ~6 lines of game code:
func _ready() -> void: for b in all_buildings: QuestData.bind_balancing(b, "buildings", "", "building_id") QuestData.bind_balancing_pivot(b, "building_costs", "building_id", "resource_costs", "resource_id", "base_amount")Dashboard edit → WS push → SDK mutates b.resource_costs in-place → done. No further code needed for the data flow.
What the SDK eliminates:
| Task | LOC without SDK |
|---|---|
| HTTP fetch + auth + retry | ~30 |
| JSON parse + type coercion | ~20 |
| Disk cache + offline fallback | ~40 |
| WebSocket poll loop + reconnect | ~50 |
Row → resource.set() mapping per field | ~10 per table |
| Pivot aggregation (rows → dict) | ~15 per dict property |
| Change detection + signal emit | ~20 |
| Total | ~185–230 LOC |
6 lines of game code replace ~185–230 LOC of infrastructure.
For the full integration guide including UI reactivity, the queue_free trap, and a reusable BalancingRefresh helper, see the Live Balancing Cookbook.
Creating Balance Tables
Section titled “Creating Balance Tables”- Go to Live Ops > Balancing
- Click New Table and enter a name (e.g., “XP_PROGRESSION”)
- Define columns:
level,xp_required,reward_amount - Add rows with data
- Click Save
The table is immediately available via the Remote Config API.
Working with Data
Section titled “Working with Data”Manual Editing
Section titled “Manual Editing”Edit cells directly in the spreadsheet. Changes are saved to a draft version until published.
CSV Import
Section titled “CSV Import”Import existing balance data:
- Click Import CSV on a table
- Select a CSV file (must match column headers)
- Review the preview
- Click Merge to replace current data
Version History
Section titled “Version History”Every published version is preserved:
| Action | Description |
|---|---|
| Preview | See what a past version contained |
| Compare | Show diff between two versions |
| Rollback | Revert to a previous version |
Example: XP Progression Table
Section titled “Example: XP Progression Table”level,xp_required,reward_coins,reward_gems1,0,0,02,100,50,13,250,100,24,450,150,35,700,200,5Query this from your game:
var xp_table = await QuestData.get_game_data("XP_PROGRESSION")var level_2_xp = xp_table[1]["xp_required"] # 100Collaborative Editing
Section titled “Collaborative Editing”- Draft mode: Multiple editors can work on the same table
- Publishing: Click Publish to make it available to games
- Audit Log: See who changed what and when
API Reference
Section titled “API Reference”# Get a tablecurl "https://api.questdata.io/v1/gamedata/XP_PROGRESSION" \ -H "x-game-api-key: YOUR_API_KEY"
# Get a specific versioncurl "https://api.questdata.io/v1/gamedata/XP_PROGRESSION?version=5" \ -H "x-game-api-key: YOUR_API_KEY"Response:
{ "table": "XP_PROGRESSION", "version": 5, "published_at": "2026-04-06T10:30:00Z", "columns": ["level", "xp_required", "reward_coins"], "rows": [ {"level": 1, "xp_required": 0, "reward_coins": 0}, {"level": 2, "xp_required": 100, "reward_coins": 50} ]}