Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Рефакторинг системы подсветки: вместо длительности в секундах теперь используется количество циклов (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`: переписана документация на актуальную структуру проекта и текущие возможности игры.
231 lines
14 KiB
Markdown
231 lines
14 KiB
Markdown
# Архитектура проекта "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`, поэтому переименование или перенос этих ассетов требует обновления строковых путей в коде.
|