Content pipeline directory structure for Godot games
A data-driven content pipeline uses a hierarchical directory structure under a `content/` root. Directory layout includes: `locations/` for room JSON files organized by act, `items/` for item data files, `dialogues/` for Yarn script files, `quests/`, `events/`, `parser/` for verb and synonym definitions, `achievements.json`, and `locales/` for CSV translation files. Within locations and items, files are organized by act (act1, act2, etc.) to facilitate designer workflow and reduce merge conflicts.
Content loader autoload pattern using DirAccess
Implement a ContentDB autoload that extends Node and loads all content at startup. The loader uses DirAccess to iterate directories, reads JSON files by ID field, and stores them in a flat Dictionary for runtime lookup. The _load_dir method takes a path, target dictionary, and id_field name; it opens the directory, iterates .json files, deserializes each with _read_json, and stores by ID. Separate _load_dir calls load different acts and content types. Provide public getter methods like get_room(id: String) -> Dictionary that return empty Dictionary if ID not found.
Room schema structure with localized state descriptions
A room JSON schema includes: id (unique identifier), name_en and name_ru (localized names), description_states (nested object mapping state names to localized description objects), current_state_initial (initial state name), exits (flat dictionary mapping direction to destination room ID), locked_exits (nested object mapping exit directions to unlock conditions with unlocked_flag and localized fail_text), items array (list of item IDs in the room), ambient_sound (sound file reference), illustration object with base image path and layers object mapping state names to arrays of layer asset names, and tags array for categorization.
Item schema structure with verb-based actions
An item JSON schema includes: id (unique identifier), name_en and name_ru (localized names), description_en and description_ru (short descriptions), examine_text_en and examine_text_ru (longer examination text), portable boolean (whether item can be taken), tags array (for categorization like 'key' or 'lore'), and actions array containing objects with verb (action type like 'use'), preposition ('on', 'with'), target (room or item ID), and effect (gameplay consequence identifier).
Content validation tool for detecting schema errors
Run a headless content validator before shipping to detect schema errors: verify all exit destinations exist in ContentDB, verify all item IDs referenced in rooms exist in ContentDB, check all localized strings are present (e.g., name_en and name_ru). Implement as a script extending SceneTree with _init method. Run via CLI: `godot --headless --script tools/content_validator.gd`. Add to CI pipeline. Exit code should be 0 on success, 1 on validation errors.
Hot-reload content during development
Implement a reload_content() method in ContentDB that clears all dictionaries (_rooms.clear(), _items.clear()) and calls _load_all() again. Emit a content_reloaded signal after reloading so systems can react. Bind reload to a debug key (e.g., 'dev_reload') via Input.is_action_just_pressed(). This allows designers to edit JSON files and see changes instantly without restarting the game during development.
Yarn Spinner for dialogue trees in Godot
Use Yarn Spinner format for dialogue content. Files contain dialogue nodes with title declarations, prose text, and branching choices using `->` syntax. Nodes support variables with `<<set >>` tags and control flow with `<<jump>>` tags. Compile Yarn files to Godot resources using YarnSpinner-Godot plugin (github.com/YarnSpinnerTool/YarnSpinner-Godot). This keeps dialogue content outside GDScript and allows non-programmers to write branching narratives.
Godot localization with CSV translation files
Store localizable text in CSV format with columns: key (identifier), then one column per language code (e.g., en, ru, de, fr). Each row is a translation key with values for each language. Load CSV file into Project Settings → Localization → Translations. In code, use the tr() function with the key string to retrieve localized text based on current locale. This keeps text content out of GDScript and allows designers to manage translations without touching code.
Schema versioning and migration for content data
Add a 'version' field to each content JSON file to track schema evolution. When loading, pass version to a _migrate(data: Dictionary, version: int) -> Dictionary function that applies transformations for old versions. Example: version 1 to 2 migration renames 'description' field to 'description_states' with nested structure. Increment version when changing schema. This allows backwards compatibility and smooth upgrades of content files without losing old data.