Files
open-wc/docs/GODOT_BEST_PRACTICES.md

121 lines
9.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Godot Best Practices for OpenWC
## Статус
Это нормативные правила применения Godot в OpenWC. Они дополняют общую архитектуру и основаны на официальных Godot practices с учётом большого streaming world, native parsers и встроенного Editor tooling.
## Nodes только на границах
- Domain, packet codecs, validators, coordinate math, build graph и canonical content не должны быть Nodes.
- Node/Control используются для lifecycle, scene composition, input, rendering/audio presentation и Editor UI.
- Большой объём однородных данных хранится в typed objects/packed arrays/resources, а не в тысячах служебных Nodes.
- Scene не ищет глобально dependency по имени; parent composition передаёт contract/reference явно.
## Scene organization
- Каждая scene имеет одну ответственность и может запускаться в isolation с test doubles.
- Parent-child означает ownership: удаление parent логично удаляет child. Иначе системы являются siblings/services.
- Scene наружу публикует небольшой API/signals, а внутренние NodePaths не становятся публичным контрактом.
- Runtime, render sandbox, preview и capture scenes собираются из общих presenters/services.
- Generated world preview не сохраняется как authoring source.
## Dependency injection и signals
- Dependencies передаются composition root, initializer или exported interface reference.
- Signals используются для notification; commands/intents вызываются через явные методы/bus contracts.
- Signal connections снимаются симметрично при unload/plugin disable.
- Не использовать SceneTree groups как скрытый service locator для core architecture.
## Autoload policy
Autoload разрешён только для действительно process-wide lifecycle:
- composition/bootstrap coordinator;
- глобальная immutable build/version information;
- crash/diagnostic sink, если ему нужен process lifetime.
Gameplay state, network session, renderer world, editor session, caches конкретного проекта и audio emitters не должны становиться неявными глобальными managers. Они создаются/освобождаются владельцем режима.
## Resources and data
- Resource подходит для immutable/imported descriptors и editor-inspectable configuration.
- Runtime mutable authoritative state не хранится в shared Resource, который может быть случайно разделён сценами.
- Resource schema имеет version и migration, если сохраняется пользователем.
- Original extracted corpus и bulk caches не следует заставлять Godot массово импортировать без необходимости; применять `.gdignore`, custom import staging или native repository.
- Importer проверяет malformed input и записывает dependency/profile metadata.
## Background work
- Blocking `load()` не используется в frame-critical streaming path; применяются threaded load/jobs.
- Worker выполняет file I/O, parsing, decompression, grouping и pure data generation.
- SceneTree mutation, Node attach и большинство GPU/RID finalization выполняются main thread budget.
- Один Resource не модифицируется несколькими workers.
- GDScript container resize/mutation между threads защищается mutex или заменяется message passing.
- Все worker tasks ожидаются/очищаются; session cancellation не оставляет orphan work.
## Rendering performance
- Сначала измерять SceneTree/CPU/GPU bottleneck, затем переходить к RenderingServer.
- Repeated static M2 группировать spatial MultiMesh cells; один MultiMesh на весь мир ухудшает culling.
- Large transform buffers готовить линейно/в native code и отправлять батчем.
- Visibility ranges/HLOD, occlusion и automatic mesh LOD использовать совместно по профилю.
- Unique materials/textures минимизировать; descriptor/resource counts являются budget metric.
- RenderingServer RIDs имеют явного владельца и освобождаются в deterministic shutdown test.
- Shader/material profiles разделяют Blizzlike и Enhanced; runtime не компилирует тяжёлые варианты при пересечении ADT boundary.
## EditorPlugin lifecycle
- Любая регистрация в `_enter_tree()` имеет соответствующее удаление в `_exit_tree()`.
- Docks, inspectors, importers, gizmos, debugger plugins, signals и jobs снимаются при disable/reload.
- Editor UI не пишет файлы/SQL напрямую — только создаёт application commands.
- Mutation интегрирована с EditorUndoRedoManager или общей command history.
- Preview nodes считаются disposable; stable content IDs не равны instance IDs.
- Долгая операция имеет progress, cancellation и staging output.
## Editor imports and inspectors
- Custom import plugin применяется для формата, которому действительно нужен first-class Godot Resource lifecycle.
- Один extension/type имеет стабильный importer name и version.
- Platform/profile variants фиксируются явно.
- Custom inspectors редактируют canonical data через commands и показывают field-level validation.
- Gizmos не владеют сущностью и создают одну undoable logical operation на drag/stroke.
## UI
- Control tree не читает network packets и не ищет world nodes.
- View models immutable на frame/update boundary.
- Layout использует anchors/containers/theme tokens, а не hardcoded pixel positions вне fidelity backend.
- FrameXML compatibility layout изолирован от modern Godot-native screens.
- Input consumption и focus/modal context тестируются сценами.
## Profiling and diagnostics
- Использовать Godot profiler для script/physics и Visual Profiler для render CPU/GPU.
- Headless/CLI runs сохраняют JSON metrics; GPU runs фиксируют backend/device/driver/resolution.
- Performance changes сравниваются cold/warm и p50/p95/p99, а не одним FPS.
- GPU validation, memory tracking и RenderDoc workflow документируются для shader/backend defects.
- Custom monitors публикуют streaming queues, cache hits, entities, materials, RIDs и job latency.
## Tests
- Pure logic тестируется без SceneTree.
- Scene runner используется только для lifecycle/input/signals/layout/presentation.
- EditorPlugin имеет enable/disable/reload и undo/save/reload tests.
- Headless является обязательным CI path; visual tests запускаются отдельно на GPU runner.
- GdUnit4 рассматривается как кандидат для GDScript/scene tests; native tests остаются отдельным target.
## Official references
- [Godot Best practices](https://docs.godotengine.org/en/stable/tutorials/best_practices/index.html)
- [Scene organization](https://docs.godotengine.org/en/stable/tutorials/best_practices/scene_organization.html)
- [Autoloads versus regular nodes](https://docs.godotengine.org/en/stable/tutorials/best_practices/autoloads_versus_regular_nodes.html)
- [Background loading](https://docs.godotengine.org/en/stable/tutorials/io/background_loading.html)
- [Thread-safe APIs](https://docs.godotengine.org/en/stable/tutorials/performance/thread_safe_apis.html)
- [Optimization using MultiMeshes](https://docs.godotengine.org/en/stable/tutorials/performance/using_multimesh.html)
- [RenderingServer](https://docs.godotengine.org/en/stable/classes/class_renderingserver.html)
- [Import plugins](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/import_plugins.html)
- [Inspector plugins](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/inspector_plugins.html)
- [3D gizmo plugins](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/3d_gizmos.html)
- [Command line tutorial](https://docs.godotengine.org/en/stable/tutorials/editor/command_line_tutorial.html)
- [Debugging tools](https://docs.godotengine.org/en/stable/tutorials/scripting/debug/overview_of_debugging_tools.html)