Прототип пошаговой тактической игры на квадратной сетке. Игрок проходит выбор команд, попадает на уровень, выбирает персонажей и способности, перемещается по сетке и выполняет действия в порядке инициативы.
Проект находится в активной разработке. Основная игровая сцена сейчас использует уровень Office, две команды персонажей, очки действий, поиск пути, зоны перемещения, удар в ближнем бою и два режима камеры.
Требуемая версия редактора: Unity 6000.4.11f1.
- Откройте корень проекта через Unity Hub.
- Дождитесь импорта ассетов и компиляции скриптов.
- Откройте
Assets/_game/Content/_Global/Game.unity. - Запустите Play Mode.
Стандартный игровой flow:
Game -> Boot -> StartMenu -> Draft -> Core
Ошибка запуска любого состояния -> Error
Для быстрого запуска используется Tools -> Runner:
RushToCoreформирует тестовые команды изDraftSettingsи сразу открываетCore;SpecifiedSceneзапускает выбранную сцену напрямую и предназначен для изолированной разработки; для полного flow выберитеGame.unity.
Game.unity должна оставаться стартовой сценой для обычной игры. Остальные игровые сцены загружаются роутером аддитивно.
- ЛКМ — выбрать персонажа, клетку или цель;
WASD— перемещение free roam камеры;Q/E— поворот камеры;- колесо мыши — приближение и отдаление;
- кнопки способностей в HUD — выбор перемещения или атаки;
- выбор персонажа переключает камеру в third person, если этот режим разрешен в
CameraSettings.
Проект построен вокруг VContainer, игровых состояний и разделения runtime-логики на services, models, systems и views.
flowchart TD
GameScene["Game.unity<br/>GameLifetimeScope"] --> Global["Глобальный scope"]
Global --> Services["Services<br/>UI и общая инфраструктура"]
Global --> Router["GameStateRouter"]
Global --> Shared["SharedGameModelsContainer"]
Router --> StateScene["Активная state-сцена<br/>Boot / StartMenu / Draft / Core / Error"]
StateScene --> StateScope["State LifetimeScope"]
StateScope --> Entry["StateEntryPoint"]
StateScope --> Models["Models<br/>состояние и события"]
StateScope --> Systems["Systems<br/>правила и реакции"]
Systems --> Models
Models --> ViewModels["ViewModels"]
ViewModels --> Views["uGUI Views"]
Shared --> StateScope
GameLifetimeScope живет в Game.unity всю игровую сессию. Он регистрирует:
GameStateRouter;- глобальные services;
- глобальные models и systems;
- общие настройки;
- dispatchers Unity update-цикла, событий и actions;
SharedGameModelsContainerдля данных, которые должны пережить смену state-сцены.
GameEntryPoint инициализирует глобальные services и systems, подключает update-системы к UpdatesDispatcher, затем открывает Boot либо сразу Core в режиме RushToCore.
Каждое состояние представлено отдельной сценой и отдельным LifetimeScope:
| Состояние | Ответственность |
|---|---|
Boot |
Инициализация и экран загрузки |
StartMenu |
Главное меню и вход в draft |
Draft |
Выбор составов двух команд |
Core |
Основной tactical gameplay |
Error |
Fallback при ошибке загрузки или запуска состояния |
GameStateRouter закрывает текущее состояние, загружает новую сцену аддитивно, назначает глобальный scope родителем state-scope и вызывает IStateEntryPoint. В сцене состояния должен быть ровно один корневой LifetimeScope.
Порядок входа в состояние:
- Инициализация models.
- Выполнение логики конкретного
EntryPoint. - Инициализация systems и регистрация update-интерфейсов.
При выходе порядок обратный: systems освобождаются в обратной последовательности, затем выполняется ExitPoint, после чего освобождаются models и выгружается сцена.
Models содержат runtime-состояние, reactive values и доменные события. Они не зависят от конкретного UI и не управляют игровым поведением напрямую.
Примеры в Core:
CoreCharactersModel— персонажи, выбранный и активный персонаж, номер раунда;CoreGridModel— runtime-сетка и найденные пути;CoreInputModel— события кликов по персонажам, сетке и внешней области;CoreCameraModel— активная камера и режим камеры;CoreLevelsModel— текущий уровень.
DraftResultModel является shared model: выбранные в Draft команды доступны после перехода в Core.
Systems реализуют правила игры, подписываются на models и записывают результат обратно в models. Systems не должны вызывать друг друга напрямую: взаимодействие проходит через состояние, события и команды models.
Основные Core systems:
- selection и обработка кликов;
- очередность ходов по инициативе и восстановление очков действий;
- построение пути и перемещение по сетке;
- расчет занятых клеток и отображение доступной зоны;
- выбор и выполнение способностей;
- free roam и third person камеры;
- рендер runtime-сетки и очереди персонажей.
System, реализующая IUpdate, ILateUpdate или IFixedUpdate, автоматически вызывается через UpdatesDispatcher, пока ее состояние активно.
Unity-компоненты используются как пассивные views с заранее сериализованными ссылками. View models подготавливают данные и команды для UI, а UGUIService создает экраны по UIViewCode из UGUISettings.
UGUIRoot создается один раз глобальным service и переживает смену state-сцен. Конкретные экраны открываются в EntryPoint и закрываются в ExitPoint.
Настройки хранятся в ScriptableObject, а ссылки на Unity-объекты задаются через Inspector. Главная точка конфигурации gameplay — CoreStateSettings, объединяющая настройки уровня, камеры и движения персонажей.
Уровень задается связкой:
LevelSettings— prefab уровня, grid data и spawn settings;LevelGridData— сериализованное описание сетки;LevelView— ссылки на геометрию и collider-поверхности;SpawnSettings— позиции появления команд.
Персонаж описывается CharacterSettings: prefab, размер footprint, характеристики и доступные способности. Значения характеристик во время игры находятся в CharacterStatsModel.
Models, systems и services регистрируются через атрибуты:
[GameModel(nameof(GameStateCode.Core))]
public sealed class ExampleModel : GameModel<ExampleModel, IExampleModel>, IExampleModel
{
}
[GameSystem(nameof(GameStateCode.Core))]
public sealed class ExampleSystem : SyncLifetime, IGameSystem
{
}
[GameService]
public sealed class ExampleService : SyncLifetime, IService
{
}После добавления или удаления такого класса откройте Whaledevelop -> ScriptsGenerator и выполните Generate Compositions.
Результат сохраняется в Assets/_game/Scripts/Generated. Эти файлы являются generated source of truth для VContainer-регистраций, их не следует редактировать вручную.
Assets/
├── _game/
│ ├── Content/ сцены, prefabs и ScriptableObject-настройки
│ │ ├── _Global/ постоянная Game-сцена и общие настройки
│ │ ├── Boot/
│ │ ├── StartMenu/
│ │ ├── Draft/
│ │ ├── Core/
│ │ └── Error/
│ ├── Scripts/
│ │ ├── _Global/ глобальный scope, state router, UI и shared data
│ │ ├── Boot/
│ │ ├── StartMenu/
│ │ ├── Draft/
│ │ ├── Core/ основной gameplay по доменным модулям
│ │ ├── Error/
│ │ ├── Editor/ Runner, генераторы и инструменты
│ │ ├── Generated/ автогенерируемые VContainer compositions
│ │ └── Utility/
│ └── Sandbox/ изолированные эксперименты
├── _whaledevelop/ переиспользуемый framework-слой проекта
└── Plugins/ сторонние runtime-плагины
Внутри Core код разделен по gameplay-доменам: Abilities, Camera, Characters, Grid, Input, Levels, Movement, Queue, Selection, Stats, Turn и UI.
Рекомендуемый маршрут чтения:
GameLifetimeScopeиGameEntryPoint— глобальная композиция и запуск.GameStateRouter— переходы между сценами и обработка ошибок.StateEntryPointBaseиStateExitPointBase— lifecycle состояния.CoreLifetimeScopeиCoreEntryPoint— сборка основного gameplay.CoreRuntimeDataComposition.Generated.cs— полный список Core models и systems.CoreCharactersModel,CoreCharacterTurnSystemиCoreCharacterMovementSystem— типичный путь данных через model и systems.CoreScreenViewModelиCoreScreenView— связь gameplay с UI.
Для новой gameplay-механики:
- Поместите runtime-состояние и события в model соответствующего домена.
- Реализуйте правила в отдельной system, работающей с models через DI.
- Добавьте
[GameModel]или[GameSystem]с нужным state-scope. - Перегенерируйте compositions через
Whaledevelop -> ScriptsGenerator. - Вынесите настраиваемые значения в
ScriptableObjectsettings. - Добавьте view/view model только для отображения и пользовательских команд.
- Проверьте полный вход и выход из состояния, включая повторный переход.
Новый state требует GameStateCode, отдельной сцены с одним корневым LifetimeScope, пары IStateEntryPoint / IStateExitPoint, записи в GameStatesSettings и добавления сцены в Build Settings.
| Технология | Назначение |
|---|---|
| Unity 6 / URP | Runtime и рендеринг |
| VContainer | Dependency injection и lifetime scopes |
| UniTask | Асинхронный lifecycle и переходы состояний |
| R3 | Reactive state и подписки |
| Input System | Gameplay и UI input |
| Cinemachine | Управление игровыми камерами |
| DOTween | Анимация перемещения и UI |
| Odin Inspector | Настройки и editor tools |
Список package-зависимостей Unity находится в Packages/manifest.json. Локальные и импортированные плагины перечислены в Assets/_whaledevelop/README.md.