Files
Dokumentace/Godot/DESIGN_DOCUMENT_GODOT.md
T

243 lines
10 KiB
Markdown

# Godot Development Guidelines
**Document Version:** v3
> **Note on Versioning:**
> - This document version is independent — reused across Godot projects
> - **Project version** source of truth: `project.godot` (`application/config/version`) mirrored in an autoload `Constants` script
> - Version propagates: `project.godot` → `Constants.gd` → code
> - `CHANGELOG.md` uses the project version
## Related Documents
- **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: `README.md`, `CLAUDE.md`, `AGENTS.md`, `DESIGN_DOCUMENT_GODOT.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.DEFAULT_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.DEFAULT_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/`Resource`s 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:
```bash
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:
```bash
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.DEFAULT_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, using the **Todo Tree** tags defined in `AGENTS.md` (`TODO`, `FIXME`, `BUG`, `HACK`, `NOTE`). `PROJECT.md` carries only cross-cutting tasks that have no single place in the code.
```gdscript
# TODO: move this into a reusable StateMachine scene
# FIXME: player clips through the floor at high speed
# BUG: hitbox stays active one frame too long
# HACK: temporary yield until the animation signal is wired up
# NOTE: must run in _physics_process, not _process
```
No other task format is used — **no checkboxes, no numbered lists in documentation**.
If a tag 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
</content>
</invoke>