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

14 KiB
Raw Blame History

Архитектура проекта "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, поэтому переименование или перенос этих ассетов требует обновления строковых путей в коде.