Danro/ARCHITECTURE.md
Danil Iarosh 79b66b2d17
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
feat: add controller disconnect/reconnect handling, MAC identification, lighting pause/resume system
- Рефакторинг системы подсветки: вместо длительности в секундах теперь
  используется количество циклов (float). Добавлена таблица длительности
  циклов эффектов `LightCycleDurations` для пересчёта циклов в секунды.
  Префикс команд подсветки изменён с `85` на `86`.
- `LightSequence`: добавлены `Pause()` / `Resume()` с запоминанием текущего
  шага последовательности; возобновление продолжает с сохранённой позиции.
- `LightController`: добавлены `PauseAll()` / `ResumeAll()` для
  приостановки и восстановления подсветки и мигания шляпы при
  отключении/переподключении платы. Свойства `IsSequencePaused`,
  `IsBlinkPaused`.
- `ComDeviceClient`: после успешной авторизации отправляются команды
  `890003` и `8600`. Добавлен запрос MAC-адреса через команду `06`
  (ответ — 12 hex-символов без префикса). Новое событие `ConnectionLost`
  при начале KeepAlive-реконнекта.
- `ComHub`: очередь `_disconnectedQueue` с типом `DeviceDisconnectMessage`
  (DeviceId + Role + Mac) — сохраняет идентификатор устройства до его
  удаления из словаря. Подписка на `ConnectionLost`.
  Добавлен `GetDeviceMac()`.
- `ComSystemManager`: при инициализации, если плата не обнаружена,
  подсветка сразу ставится на паузу. При отвале дефолтного устройства —
  `PauseAll()`, при переподключении — сравнение по MAC и роли через
  `IsSameDevice()`: та же плата → `ResumeAll()`, другая → `Blink()` с нуля.
  Добавлены событие `OnDeviceDisconnected` и метод `GetDeviceMac()`.
- `COMInput`: при событии `OnDeviceDisconnected` сбрасываются все состояния
  кнопок через `ResetAllButtons()`, генерируя `buttonUp` для зажатых кнопок.
  Устраняет баг залипания управления после переподключения платы.
- `GameManager`: расширена последовательность световых эффектов в меню
  (добавлены `DiagonalWave3`, `WaveUp`, `OrangeWave`); вызовы `SetLight`
  для game over/won переведены на float-циклы.
- Обновлены `ARCHITECTURE.md` и `README.md`: переписана документация
  на актуальную структуру проекта и текущие возможности игры.
2026-03-04 13:55:08 +03:00

231 lines
14 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.

# Архитектура проекта "Mario-like platformer"
## Обзор
Проект представляет собой 2D-платформер на Unity. Архитектура построена вокруг одного постоянного `GameManager`, набора сервисных менеджеров в `Globals`, компонентного игрового поведения на сценах и отдельной системы ввода, которая может работать как от клавиатуры, так и от COM-устройств.
Код в основном разделен по доменным папкам внутри `Assets/Scripts`, а логика сцены собирается из независимых `MonoBehaviour`-компонентов.
## Технологический стек
- Unity (2D-проект);
- C#;
- Unity Input System;
- Unity UI (`com.unity.ugui`);
- Cinemachine;
- Universal Render Pipeline;
- Visual Effect Graph;
- `PlayerPrefs` для части runtime-данных;
- JSON через `JsonUtility` для сохранения настроек.
## Актуальная структура проекта
### `Assets/Scripts/Abstract`
Базовые перечисления и интерфейсы, на которых держатся общие контракты игрового кода:
- `Enums.cs`;
- `Interfaces.cs`.
### `Assets/Scripts/Managers`
Глобальные менеджеры и сервисы верхнего уровня:
- `GameManager` - центральная точка управления сессией;
- `AudioManager` - музыка, пауза и SFX;
- `PaymentManager` - кредиты и логика оплаты;
- `BalanceManager` - баланс для запуска/продолжения игры;
- `InactivityManager` - реакция на бездействие;
- `GlobalsManager` - инициализация общих зависимостей;
- `PrizeSystemManager` - управление призовой системой.
### `Assets/Scripts/Settings`
Новая система настроек, отделенная от игрового цикла:
- `Core/SettingsManager` - хранение значений, загрузка, сохранение, рассылка событий;
- `Core/SettingsDatabase` - схема настроек и значения по умолчанию;
- `Core/SettingsApplier` - применение значений к рантайм-системам;
- `UI/*` - генерация и связывание интерфейса настроек.
### `Assets/Scripts/Controls`
Подсистема ввода и интеграции с внешним оборудованием:
- `Inputs/In.cs` - фасад поверх выбранного источника ввода;
- `Inputs/InputSource*` - абстракции и реализации источников;
- `Inputs/KeyboardInput.cs` - клавиатурное управление;
- `Inputs/COMInput.cs` - чтение данных с COM-контроллера;
- `Inputs/ComSystem/*` - подключение устройств, handshake, освещение, призовые стойки и маршрутизация сообщений;
- `ComInputToInputSystemAdapter.cs` - адаптер в сторону Unity Input System.
### `Assets/Scripts/Behaviour`
Основная игровая логика, размещаемая на объектах сцен:
- `Controllers/*` - игрок, враги, сценовая музыка;
- `Camera/*` - слежение и ограничение поведения камеры;
- `Checkpoints/*` - точки возрождения и текущий активный чекпоинт;
- `Projectiles/*` и `ThrowProjectiles/*` - снаряды и логика стрельбы;
- `Sequence/*` - сценарные последовательности действий;
- `Health`, `LevelFinish`, `ScoreSystem`, `MessageController`, `Parallax`, `LightDimmer`, пулы VFX и окружения.
### `Assets/Scripts/Entities`
Интерактивные сущности уровня:
- платформы (`MovingPlatform`, `ShiftingPlatform`, `TrajectoryPlatform`, `VanishingPlatform`, `TriggeringPlatform`, `HidingTriggeringPlatform`);
- собираемые объекты (`CoinCollectible`, `LeafCollectible`, `BatCollectible`);
- ловушки и рычаги (`Trap`, `Lever`, `DeactivatingLever`);
- прочие физические объекты (`JumpPad2D`, `Rotator`, `Oscillator`, `LightActionsController`).
### `Assets/Scripts/UI`
Пользовательский интерфейс игры и служебные окна:
- главное меню, пауза, выбор уровня, финальные баннеры;
- верхняя панель статуса, отображение кредитов и баланса;
- модальная система (`UI/Modal`);
- текстовый ввод (`UI/TextInput`);
- служебные окна статистики и QR-кодов.
### Дополнительные домены
- `Audio` - обвязка звуковых эффектов и сценовых аудио-наборов;
- `Animations` - обработчики animation events;
- `FX` - запуск визуальных эффектов;
- `ScriptableObjects` - конфигурация врагов, SFX и sequence actions;
- `Utilities` - логирование, утилиты, атрибуты, QR-коды, форматирование и отладочные настройки;
- `Editor` - кастомные инспекторы и drawers.
## Ключевые runtime-компоненты
### `GameManager`
`GameManager` создается автоматически через `RuntimeInitializeOnLoadMethod`, живет между сценами и является главным координационным узлом:
- инициализирует логгер;
- поднимает `AudioManager`;
- загружает prefab `Resources/Prefabs/Global/Globals`;
- получает ссылки на `SettingsManager`, `PaymentManager`, `BalanceManager`, `ComSystemManager`;
- управляет паузой, жизнями, монетами, переходами между уровнями и спавном игрока;
- публикует основные события игры (`PauseStateChanged`, `PlayerSpawned`, `CoinsChanged`, `LivesChanged`, `GameOverEvent`, `GameWonEvent`).
### `Globals`
Глобальный prefab из `Resources/Prefabs/Global/Globals` выступает контейнером для постоянных компонентов, которые должны существовать независимо от текущей сцены. Через него `GameManager` подцепляет сервисы настроек, оплаты и COM-системы.
### `SettingsManager`
Новая подсистема настроек работает независимо от старой игровой логики и хранит значения в `persistentDataPath/settings.json`:
- читает схему из `SettingsDatabase`;
- приводит входные значения к допустимому диапазону через `Sanitize`;
- применяет изменения сразу через `SettingsApplier`;
- сообщает об изменениях через `OnSettingsLoaded`, `OnSettingsSaved`, `OnSettingChanged`.
### `ComSystemManager`
Подсистема внешних устройств отвечает за:
- обнаружение одного или нескольких COM-устройств;
- handshake и идентификацию роли устройства;
- прием монет и обновление кредитов;
- маршрутизацию входных битов от контроллера;
- управление подсветкой через `LightController`;
- подключение специализированных обработчиков, например призовой стойки.
## Потоки управления
### Запуск приложения
1. Unity вызывает автоматическую инициализацию `GameManager`.
2. `GameManager.Awake()` создает логгер, аудио и поднимает `Globals`.
3. Из `Globals` получаются ссылки на настройки, оплату, баланс и COM-систему.
4. После загрузки сцены уровня `GameManager` пытается заспавнить игрока в `PlayerSpawn`.
### Старт игровой сессии
1. `GameManager.NewGame()` проверяет режим бесплатной игры и доступный баланс.
2. Баланс конвертируется в стартовое число жизней.
3. Сбрасываются монеты и статистика (`ScoreSystem`).
4. Загружается сцена первого уровня и аддитивно сцена `Level UI`.
### Смерть и возрождение
1. Игровой объект получает урон через `Health`.
2. При необходимости вызывается `GameManager.RespawnPlayer()`.
3. Менеджер уменьшает число жизней.
4. Если жизни есть, игрок переносится к активному чекпоинту или стартовой точке.
5. Если жизни закончились, вызывается событие окончания игры.
### Переход между уровнями
1. `LevelFinish` или другая игровая логика вызывает `GameManager.NextLevel()`.
2. `GameManager` вычисляет следующую сцену по схеме `world-stage`.
3. Если сцена существует в build settings, она загружается.
4. Если следующей сцены нет, игра считается пройденной.
## Архитектурные принципы
### Компонентная модель Unity
Игровая логика вынесена в независимые `MonoBehaviour`, которые комбинируются на prefab-ах и объектах сцен. Большинство сущностей собирается из небольших компонентов вместо глубокой иерархии наследования.
### Централизованное orchestration + событийная связь
`GameManager` координирует верхнеуровневый поток игры, но отдельные подсистемы общаются через события, а не через жесткие прямые вызовы между всеми слоями.
### Конфигурация через `ScriptableObject`
Настройки, конфигурации врагов, аудио-наборы и сценарные действия вынесены в ресурсы, чтобы часть поведения менялась без переписывания кода.
### Разделение по доменам
Код разделен не по техническим слоям MVC, а по игровым областям ответственности: `Managers`, `Behaviour`, `Controls`, `UI`, `Entities`, `Settings`.
### Фасад над вводом
`In.cs` скрывает конкретный источник сигналов от остального игрового кода. Благодаря этому один и тот же gameplay-код может работать и с клавиатурой, и с COM-платой.
## Сцены и ресурсы
### Сцены
В проекте явно присутствуют:
- `MainMenu`;
- `Level UI`;
- игровые сцены уровня (например, `1-1`, `99-99`) по шаблону `world-stage`.
### `Resources`
Критичные runtime-ресурсы, которые подгружаются из кода:
- `Prefabs/Global/Globals`;
- `Prefabs/Player_New` (или альтернативный player prefab);
- `Audio/Master`;
- `SettingsDatabase`.
Это означает, что проект по-прежнему опирается на `Resources.Load` для части базовой инициализации.
## Пространства имен
Основные пространства имен в текущем коде:
- `RR.Game2D.Core.Managers`;
- `RR.Common.Settings`;
- `RR.Common.Controls`;
- `RR.Common.Behaviour`;
- `RR.Game2D.Behaviour`;
- `RR.Game2D.Entities`;
- `RR.Common.Utility`.
## Что важно учитывать при изменениях
- `GameManager` остается точкой входа и зависит от структуры `Globals`; изменения в prefab-е могут ломать инициализацию всей игры.
- Схема имен сцен (`1-1`, `1-2` и т.д.) встроена в логику переходов между уровнями.
- Настройки частично влияют на базовый gameplay (`startLives`, `additionalLives`, параметры оплаты).
- COM-подсистема тесно связана с аркадным режимом: кредиты, свет, призовые устройства и внешний ввод.
- Для части критичных объектов используются пути в `Resources`, поэтому переименование или перенос этих ассетов требует обновления строковых путей в коде.