5.4 KiB
Архитектура
Документ описывает, как устроен проект: какие есть слои, кто кому имеет право звонить и как данные ходят по системе. Структура папок — прямое отражение этих слоёв, см. README.
Слои и правила зависимостей
Стрелка «→» читается как «может знать о». Всё, что не указано, — запрещено.
main ──→ autoload ──→ core
│
├───→ ui ────────→ core, data
├───→ world ─────→ core, data, entities
├───→ systems ───→ core, data
├───→ entities ──→ core, data
└───→ debug ─────→ (всё, только для разработки)
| Слой | Зачем | Чего в нём быть не должно |
|---|---|---|
core |
Утилиты, базовые типы, математика сетки | Ссылок на конкретные сцены и геймплей |
data |
Описания контента: схемы (Resource) и их экземпляры (.tres) |
Логики поведения — только данные |
systems |
Симуляция мира: время, климат, погода, экономика | Прямого доступа к нодам сцены |
world |
Визуализация и взаимодействие с убежищем | Правил симуляции — они в systems |
entities |
Жители, предметы; их состояние и поведение | Знания о конкретном UI |
ui |
Экраны, HUD, контролы | Изменения состояния мира напрямую |
debug |
Дев-консоль, оверлеи, читы | Кода, от которого зависит релизная логика |
Ключевое правило: ui и world не меняют состояние мира сами — они шлют
намерение (сигнал/вызов системы), а изменение делает systems. Обратно
systems не дёргает ноды: он сообщает об изменении сигналом.
Данные и рендер разделены
Симуляция не должна зависеть от того, нарисовано ли что-то на экране.
- Данные (
systems,data) — чистая логика: считаются отdelta, полностью сериализуемы, тестируются без дерева сцены. - Рендер (
world,ui) — читает данные и отображает, подписавшись на сигналы.
Практический критерий: любой класс из systems должен работать в юнит-тесте,
где никакой сцены нет.
Обмен сообщениями
Три способа, в порядке предпочтения:
- Сигнал вверх, вызов вниз. Родитель знает о детях и вызывает их методы; ребёнок о родителе не знает и только испускает сигналы.
- Ссылка на систему, полученную из автозагрузки — когда нужен ответ здесь и сейчас (запрос состояния, валидация постройки).
- Глобальная шина (
EventBusвautoload) — только для событий, которые слушают несколько несвязанных слоёв (например, «время перескочило», «погода сменилась»). Не превращать её в свалку: каждый сигнал документируем.
Контент — это ресурсы, а не код
Новая комната, предмет или тип породы добавляются как .tres в data/tables/
по схеме из data/resources/, без правки кода. Если для добавления контента
приходится менять .gd — схема неполная, чинить надо схему.
Автозагрузки
Автозагрузка — дорогая вещь: она живёт всю сессию и её видно отовсюду. Заводим только для того, что действительно глобально и одно на игру. Каждая новая автозагрузка регистрируется через Project Settings → Autoload и упоминается здесь.
Сейчас в проекте: _mcp_game_helper — служебная, часть плагина godot_ai,
к игровой логике отношения не имеет.
Решения
Существенные развилки (выбор подхода к сохранению, к сетке, к тайм-степу)
фиксируем как ADR в adr/ — короткая заметка «контекст → решение →
последствия». Это дешевле, чем через полгода восстанавливать мотивацию по коду.