doc 1 of 5

Data-Driven Design — code for the shape, data for the values

Every game in this almanac hit the same wall and broke through it the same way. The farming game's stage 04: a turnip and a potato that "differ only in data — textures, days per stage, yield." The survivors game's stage 03: a Golem variant that's a species because its numbers live on EnemyStats, not in the controller. Its stage 07: an upgrade that's a .tres file, and "the entire upgrade system's content: two files, zero code." The 3D farm's stage 05: the carrot added with zero code changes, and that sentence is the design's acceptance test.

The pattern is one, and it has three names depending on which edge you're looking at: the definition/state split (what a kind is versus what this one is), the catalogue (the roster of definitions the game can look up), and data-driven (the property that adding content is a file operation, not a code operation). This shelf is the general treatment of the thing the curricula each used a slice of.

What this shelf teaches#

PartYou buildRight when
01The @export family, and the test that decides where a number livesYou have a hardcoded constant and a second instance that should differ
02The definition/state split, the never-mutate rule, and the three containersA "kind" has more than one number, and instances of it must disagree
03The roster + index, ids as StringName, the bad-id warningThe game needs to find a definition by name at runtime
04The fences — enums, versioned data, the save seam — and where data-driven stopsA designer (or future-you) will change the data without touching the code

The rule the shelf keeps returning to#

If two things of the same kind could ever disagree about a value, it's state, not definition. The 3D farm's version, in full: days_grown is per-plant (two turnips, planted a day apart, disagree) so it lives on Plot; days_per_stage is per-kind (every turnip agrees) so it lives on CropData. The line between the two is the whole design, and every bug this shelf's parts meet is a value that crossed the line in the wrong direction — state on a definition (all the turnips grow at once) or definition on state (a number that should be data is welded into a script).

What data-driven actually buys you#

  • Content is a file. The third crop, the fourth upgrade, the second enemy species — each is a .tres (or a scene variant), reviewed in a diff the way code is, and addable by someone who's never read the controller. The shape is code; the values are content.
  • The inspector is a design surface. A weapon's @export_subgroup("Weapon Stats") block (the survivor's stage 05) reads as a stat sheet. You can look at the game's balance without opening a script, which is the difference between "the numbers are in the code" and "the numbers are in the game."
  • Saving is a walk. The 3D farm's stage 07: serialize _plots — cell to {crop id, stage, days_grown} — and the save is the data layer, not the scene tree. The save & load shelf's opening audit passes because the truth is data; it fails the day a value crosses the line into a visual.

What it doesn't buy you#

Data-driven is not a plugin system, and the moment it's reached for as one, it's stopped being a design tool and started being an architecture. A WeaponUpgrade with an upgrade_type enum is data — the set of upgrade kinds is closed, and a new kind is a new enum value plus a match branch, which is code, by design. A "upgrade that runs a script" is a system, and it deserves a system's review, a version, and a failure mode. Part 04 is the fence between the two, and it's the part most likely to save you from yourself.

Prerequisites#

  • Custom Resources — the definition is a class_name … extends Resource. The farming game's stage 04 builds the first one; the programming shelf's typed GDScript covers the class_name and typed-array rules this shelf stands on.
  • Signals — the definition/state split earns its keep when observing the state is a signal (Inventory.changed, the inventory shelf). A data model with no observers is a data model you have to remember to re-read.
  • The curricula are the test cases; this shelf is the treatment. Read a part after you've met the pattern in a stage and it's a generalization; read it before and it's a map of where the stages are going.

Where this shows up in the projects#

The 3D farm is the shelf's cleanest instance — CropData / Plot / Crop is the definition/state/view triple in its purest form, and stage 05's zero-code carrot is part 02's acceptance test run in a real project.

The survivors game is the shelf at combat scale — EnemyStats (part 01's per-kind numbers), WeaponUpgrade (part 02's immutable definition applied to mutable state), the weapon's upgrade_list and the farm's crop_catalogue (part 03's roster), and stage 07's upgrade_type enum (part 04's fence).

The farming game is the origin — CropData as the first custom Resource in the almanac, and stage 06's Inventory as the first observer of a data layer. The inventory shelf is that stage's general treatment; this shelf is the pattern that stage and inventory both sit on.