Files
Dokumentace/Godot/DESIGN_DOCUMENT_GODOT.md
T

9.6 KiB

Godot Development Guidelines

Document Version: v1

Note on Versioning:

  • This document version is independent — reused across Godot projects
  • Project version source of truth: project.godot (config/version) mirrored in an autoload Constants script
  • Version propagates: project.godotConstants.gd → code
  • CHANGELOG.md uses the project version
  • README.md — Project overview, gameplay description, build/run instructions
  • AGENTS.md — Rules for AI assistants
  • PROJECT.md — Project goals and current state
  • CHANGELOG.md — Version history

Documentation Organization

All detailed documentation of features and systems belongs in the docs/ folder, not in the project root.

The root directory contains only the core documents: DESIGN_DOCUMENT_GODOT.md, AGENTS.md, PROJECT.md, CHANGELOG.md.


1. Code Style

  • GDScript style guide (official Godot conventions), 100-character soft line limit
  • Tabs for indentation (Godot default, enforced by .editorconfig)
  • snake_case functions/variables/signals, PascalCase classes/nodes/scenes, SCREAMING_SNAKE_CASE constants, _leading_underscore for private members
  • Static typing required on all variables, parameters, and return types (var speed: float, func move(delta: float) -> void)
  • Declaration order inside a script:
    1. class_name / extends
    2. ## docstring
    3. signals
    4. enums, constants
    5. @export variables
    6. public variables
    7. private variables (_)
    8. @onready variables
    9. _init, _ready, _process, _physics_process virtuals
    10. public methods
    11. private methods (_)
    12. signal callbacks (_on_*)

2. SOLID Principles (applied to nodes & scenes)

  • SRP — One scene/script = one responsibility (a node does one job)
  • OCP — Extend behaviour by composing child nodes or new scenes, not by editing shared base scripts
  • LSP — A scene inheriting another must be usable wherever the parent is
  • ISP — Prefer small, focused signals and interfaces over god-objects
  • DIP — Depend on abstractions: reference behaviours via exported node paths / resources, not hard-coded global lookups

3. Dependency Injection

Inject dependencies through @export variables or _init parameters, set in the editor or by the spawning parent. Avoid reaching across the tree with get_node("/root/...") for collaborators. Use autoload singletons only for genuinely global services (audio bus, save system, game state).


4. Composition Over Inheritance

Prefer node composition and reusable scenes (e.g. a Hitbox, Hurtbox, StateMachine scene attached as a child) over deep script inheritance. Use class_name for shared base behaviour only when an "is-a" relationship is real.


5. Data Structures and Resources

  • Use Resource (class_name, extends Resource) for designer-editable, serializable data (enemy stats, level definitions, weapon configs) — saved as .tres
  • Use plain typed Dictionary/Array or small data classes for transient in-memory structures
  • Validate Resource fields with @export_range, setters, and _get_configuration_warnings() where appropriate

6. Logging and Console Output

Logging

Use a dedicated Log autoload that wraps print/push_warning/push_error with levels and timestamps. Never log secrets, passwords, tokens, or API keys.

Log sinks

Sink Level Format
File user://logs/{AppName}_{time}.log DEBUG full (timestamp + level + message)
Editor Output / stdout INFO full

The file sink retains max 10 log files. Each run creates a new file via the timestamp in the filename.

The DEBUG sink is only active when Constants.DEBUG is true (controlled by an ENV_DEBUG value read at startup, e.g. from a user://settings.cfg or an export feature tag).

Additional sinks (e.g. an in-game debug overlay / console panel) may be added per project.

Log levels

Level When to use
DEBUG Per-frame / per-entity detail: state transitions, collision events, per-tile operations
INFO User-visible milestones: level loaded, game saved, scene changed
WARNING Recoverable issues: missing optional resource, fallback asset used
ERROR Failures the player/dev must know about: failed save, missing required scene/resource

Console output — print()

print() is allowed for quick editor-time inspection during development. It is not a substitute for the Log autoload and must not remain in shipped gameplay code for event tracking. Use push_warning/push_error so messages appear in the editor Debugger.


7. Settings and Secrets

  • Store user/runtime config in user://settings.cfg via ConfigFile
  • Toggle debug behaviour with an ENV_DEBUG-style flag read at startup into Constants.DEBUG
  • Never commit any secrets; keep them out of project.godot and committed .tres/.cfg files

8. Error Handling

Fail fast in development: use assert() for invariants that must hold (these are stripped in release builds). For recoverable runtime conditions, check return values and is_instance_valid() before use, and surface problems via push_error/Log.error rather than silently continuing.


9. Testing

  • Use GUT (Godot Unit Test) for unit and integration tests
  • Tests live in tests/, files named test_<thing>.gd, methods named test_<action>_<context>
  • Arrange-Act-Assert pattern
  • Keep logic testable: put game rules in plain scripts/Resources that can be exercised without a running scene tree where possible

10. Tooling

Tool Purpose
gdformat (gdtoolkit) Formatting
gdlint (gdtoolkit) Linting / style checks
GUT Testing

Run before every commit:

gdformat .
gdlint .
godot --headless -s addons/gut/gut_cmdln.gd -gdir=res://tests -gexit

11. Dependencies and Addons

  • Install editor plugins/addons under addons/ (via the Asset Library or git submodule)
  • Enable plugins through Project Settings → Plugins (recorded in project.godot)
  • Keep addons/ committed so the project opens cleanly on any machine
  • Document non-trivial addon requirements in README.md

12. Project Structure

project/
├── project.godot            # Engine config and project settings
├── icon.svg                 # Project icon
├── autoload/                # Global singletons (Constants, Log, GameState, Audio)
├── scenes/                  # Game scenes (.tscn), grouped by domain
│   ├── actors/              #   player, enemies, NPCs
│   ├── levels/              #   level/world scenes
│   └── ui/                  #   menus, HUD
├── scripts/                 # Shared scripts not bound to a single scene
├── resources/               # .tres data resources (stats, configs)
├── assets/                  # Art, audio, fonts (raw + imported)
├── addons/                  # Editor plugins / third-party addons
├── tests/                   # GUT tests
└── docs/                    # Detailed documentation

Scenes and their attached scripts live together; co-locate Player.tscn and player.gd under scenes/actors/.


13. Distribution and Deployment

When the game is distributed as a standalone build:

  • Configure export presets in export_presets.cfg (one preset per target platform)
  • Build with the headless editor:
    godot --headless --export-release "Windows Desktop" build/Game.exe
    
  • Compiled builds are stored in build/ (or dist/). Decide per project whether builds are committed — for small internal distribution the repository may serve as the channel; otherwise keep build/ in .gitignore
  • Strip debug-only nodes and disable Constants.DEBUG in release presets

This section applies only to projects that produce shippable builds.


14. Versioning

  • Follow semantic versioning: MAJOR.MINOR.PATCH
  • Version is defined in project.godot (application/config/version) and mirrored in the Constants autoload
  • Always ask before bumping the version — never increment automatically
  • Update CHANGELOG.md before bumping the version

15. Documentation and Task Management

  • Keep PROJECT.md and CHANGELOG.md up to date when making changes
  • Document architectural changes in this file or in docs/

Task notation

Tasks are written as single-line comments directly in code, or in PROJECT.md for cross-cutting concerns:

# TODO: one-liner description of a task to be done
# FIXME: one-liner description of a known bug to be fixed

No other task format is used — no checkboxes, no numbered lists in documentation.

If a # TODO: comment already exists at a specific location in code, do not repeat it in PROJECT.md.


16. Godot-Specific Conventions

  • Signals over polling — communicate events upward via signals; call down via direct method calls (_on_* callbacks for receiving)
  • @onready for node references — cache child node references instead of repeated get_node
  • _process vs _physics_process — gameplay/physics in _physics_process(delta), visual-only/UI in _process(delta)
  • Groups for broadcast queries (add_to_group, get_tree().call_group) instead of manual node lists
  • queue_free() to remove nodes; never free() a node mid-signal
  • Scene instancing via PackedScene.instantiate(); keep scenes self-contained and parametrized through @export
  • No hard-coded paths to assets in code — load via preload/@export of the resource