godot-architecture
Godot architecture (gameplay programmer and architect)
Version 0.1 (2026-10-02), part of Godot Expert Skills v0.1. Target: Godot 4.7.2.stable, macOS Apple Silicon.
Expert architecture in Godot means scenes that run alone, data in Resources, behaviour in small components, and every boundary (save file, input, export) proven by a test. This skill holds the expert rules from the sources, corrected where Godot 4.7.2 behaves differently, plus a tested G1 core (inventory, health and damage, save and load, input with rebinding) and the tools that build and audit it.
REQUIRED BACKGROUND: godot-expert (channels, gd_run, the review loop, 4.7 traps).
Status (2026-10-02, round 2): everything below ran in Godot 4.7.2 here. 12 live tests: 11 pass, the C# check was not run. 30 GUT tests and 17 offline lint checks also pass; round-2 probes are P15 to P17 in references/procedures.md.
Stance (the expert delta)
- Every scene runs alone; the owner injects. A scene that reaches up (
get_node("/root/..."),../) is coupled to one tree. Use "call down, signal up, event out" (Eric Peterson, yB3Wv-Lr7pg [00:05:54]; Godot docs, Scene organization). An event bus autoload holds signals and no state (Peterson [00:17:36]). State is owned high in the tree and injected downward, because_readyruns children first (Mark Wilson, BgrHnJDt2ww [00:12:29]).arch_audit.gdinstantiates each scene alone and flags errors, NodePaths that do not resolve and node exports left empty. - Definitions are Resources; per-instance state is not. Keep item databases in typed custom Resources, not Dictionaries: no id typos, and paths follow file moves (Godotneers, 4vAkTHeoORk [00:12:57]). A loaded Resource is one shared instance: a change through one reference is seen by the next
load()(verified), so treat definitions as read-only. Stacks, health and cooldowns go in RefCounted or Node objects. For a per-instance copy (durability, rolled stats) useduplicate()when the Resource is flat, andduplicate_deep(Resource.DEEP_DUPLICATE_ALL)when it holds external sub-resources:duplicate(true)kept those shared (verified). One Resource class per file, and a default for every_initparameter (Godot docs, Resources): an inner-class Resource reloaded its field as null, and_init(p_hp)without a default lost its fields (verified). - Never list folders at runtime; build a registry at edit time. Folder scans work in the editor and break in exports (Godotneers [01:13:35]). In an exported
.pck,DirAccess.get_files_atreturned only*.tres.remap(a naive scan loaded 0 of 3), whilelist_directoryand theItemCatalogfrombuild_catalogfound all 3 (verified). The pack is case-sensitive: a wrong-case path loaded on macOS with only a "Case mismatch" warning and did not exist in the pack, so name every file and folder in lowercase snake_case (Godot docs, Project organization; lint A11, A12). A.gdignoremust be empty and takes no patterns (lint A15). It hides a folder from the importer, not fromload(): an.svginside failed with "No loader found", while a text.tresstill loaded (verified [added]). - A save file is data, never code. Verified 4.7.2 [added]:
- a
.treswritten touser://with an embedded GDScript ran that script onload(); str_to_varandConfigFile.parseboth built a Node fromObject(Node,...)text.
- a