Cabaret Template is an opinionated Godot 4.6 starter project for building a small-to-medium game with:
- A lightweight Node-based ECS (entities + components + systems) for gameplay logic
- A Redux-style state store (actions/reducers/selectors) for deterministic state + UI/navigation
- A scene manager with transitions, overlays, preloading, and caching
- A unified input stack (keyboard/mouse, gamepad, touchscreen) with profiles + rebinding
- A real GUT test suite + style/scene-structure enforcement
- Install Godot 4.6.
- Open
project.godotin Godot. - Press Play:
scenes/root.tscnboots persistent managers and loads the initial scene (main_menuby default).
- Persistent root scene (
scenes/root.tscn) with global managers and containers - Scene transitions (
instant,fade,loading) + transition queue with priorities - UI overlay stack (pause/settings/rebind/etc) driven by navigation state
- Scene registry:
- Critical scenes are hardcoded for boot safety
- Non-critical scenes can be added via
.tresresources underresources/scene_registry/
- ECS:
BaseECSComponent,BaseECSSystem,M_ECSManager- Entity IDs + tags, component queries, query caching + optional query metrics
- ECS event bus for decoupled gameplay events
- State store (
M_StateStore):- Slice-based state, action history (debug), persistence, and handoff across scene transitions
- Helpers for safe lookup + async readiness (
U_StateUtils.await_store_ready())
- Input system:
- Active device detection + centralized device types
- Input sources (
I_InputSource) for keyboard/mouse, gamepad, and touchscreen - Input profiles (
resources/input/profiles/) + Redux-driven rebinding - Optional desktop touchscreen smoke testing via
--emulate-mobile
- Testing:
- GUT runner (
addons/gut) with headless scripts - Mock ECS manager + mock state store for isolated system tests
- GUT runner (
- Faster iteration: core glue (scene transitions, UI overlays, input, persistence) already exists
- Determinism by default: gameplay systems dispatch actions; UI reads selectors and reacts
- Clear boundaries: root managers vs per-gameplay-scene ECS, plus explicit service dependencies
- Template-friendly: content can be added via Resources, not only code
scenes/root.tscn persists for the entire session:
Root
├─ Managers
│ ├─ M_StateStore
│ ├─ M_SceneManager
│ ├─ M_TimeManager
│ ├─ M_SpawnManager
│ ├─ M_CameraManager
│ ├─ M_CursorManager
│ ├─ M_InputProfileManager
│ ├─ M_InputDeviceManager
│ └─ M_UIInputHandler
├─ ActiveSceneContainer (gameplay scenes are loaded here)
├─ UIOverlayStack (pause/settings/etc)
├─ TransitionOverlay
└─ LoadingOverlay
Gameplay scenes (e.g., scenes/gameplay/gameplay_base.tscn) each include their own M_ECSManager and a standard tree layout (systems/entities/environment/etc).
On boot, scripts/root.gd registers manager nodes in U_ServiceLocator for fast access and validates declared dependencies. Most code should use:
U_ServiceLocatorfor global managersU_StateUtilsfor store lookup/readinessU_ECSUtilsfor ECS manager/entity discovery
- Update project name/icon:
project.godotconfig/nameconfig/icon
- Replace sample scenes under
scenes/gameplay/and updateresources/scene_registry/cfg_*_entry.tresaccordingly - Review
resources/input/profiles/and tune defaults underresources/input/* - Replace placeholder art under
assets/ - Skim the conventions docs:
docs/general/STYLE_GUIDE.mddocs/general/SCENE_ORGANIZATION_GUIDE.mddocs/general/DEV_PITFALLS.md
- Duplicate
scenes/gameplay/gameplay_base.tscn. - Keep the standard scene tree structure (see
docs/general/SCENE_ORGANIZATION_GUIDE.md). - Register it via a resource entry:
- Create an
RS_SceneRegistryEntryunderresources/scene_registry/ - See
docs/scene_manager/ADDING_SCENES_GUIDE.md
- Create an
- Create
scripts/ecs/components/c_<name>_component.gdextendingBaseECSComponent. - Prefer
@exportNodePaths/resources + typed getters; treat missing paths as “feature disabled”. - If you add new exported settings fields, update the corresponding default
.tresunderresources/.
- Create
scripts/ecs/systems/s_<name>_system.gdextendingBaseECSSystem. - Implement
process_tick(delta). - Add the system node to your gameplay scene under
Systems/*. - Query via
get_components(StringName(...))orquery_entities([...]).
- In
_ready(), preferawait U_StateUtils.await_store_ready(self)(avoids race conditions). - Dispatch only via action creators under
scripts/state/actions/. - Prefer selectors under
scripts/state/selectors/for reads.
- Screen metadata lives in
resources/ui_screens/cfg_*.tres(RS_UIScreenDefinition). U_UIRegistrypreloads/registers definitions for export determinism; add new screens there.- UI typically drives flow by dispatching navigation actions (rather than calling the scene manager directly).
This repo uses GUT (addons/gut). A helper script is provided:
- Run all tests:
tools/run_gut_suite.sh - Run unit tests:
tools/run_gut_suite.sh -gdir=res://tests/unit - Run style enforcement:
tools/run_gut_suite.sh -gdir=res://tests/unit/style
tools/run_gut_suite.sh uses GODOT_BIN (defaults to /Applications/Godot.app/Contents/MacOS/Godot on macOS):
GODOT_BIN="/path/to/Godot" tools/run_gut_suite.sh -gdir=res://tests/unit- General pitfalls:
docs/general/DEV_PITFALLS.md - Naming/prefix conventions:
docs/general/STYLE_GUIDE.md - Scene tree conventions:
docs/general/SCENE_ORGANIZATION_GUIDE.md - Manager dependency graph:
docs/architecture/dependency_graph.md - ECS ↔ state contract:
docs/architecture/ecs_state_contract.md - Scene registry workflow:
docs/scene_manager/ADDING_SCENES_GUIDE.md
