1. Из каких частей состоит GameFlow
| Часть | Ответственность |
|---|---|
GameFlowBootstrap | Вход в игру или тестовую сцену: создаёт корневой сервис и стартовую цепочку состояний. |
Service_GameFlow | Корневое состояние. Инициализирует библиотеку, создаёт граф, предоставляет открытие состояний, Back и Reboot. |
FlowLibrary | ScriptableObject с AssetRefs на состояния и зависимостями от других библиотек. |
FlowGraph | Логическая структура открытых узлов, их вложенности и истории переходов. |
FlowNode | Конкретное открытие состояния: положение в графе, входные параметры, данные и история. |
State | MonoBehaviour на префабе, который реализует поведение и представление состояния. |
GameStage | Крупное состояние со своим GameContext, дочерними состояниями и общим временем жизни. |
TransitionHost | Отслеживает логическую цель и показанное состояние, последовательно исполняет визуальные переходы. |
StateTransition | Планирование и исполнение скрытия старых и показа новых состояний. |
В старых разделах документации исполнитель переходов также называется Transition Root. Далее используется название TransitionHost из Scripting API. Важно понимать его роль: логический граф и визуальное исполнение перехода разделены.
2. State: поведение, входные данные и результат
GameState — название архитектурной роли. Базовый класс в пакете называется State. Чтобы создать своё состояние, нужно унаследоваться от него и сделать префаб с этим компонентом. Состоянием может быть окно Settings, HUD, пауза, диалог, катсцена или бой с боссом.
У State есть доступ к Flow, Graph, текущему Node, OpenParams и ближайшему GameStage. Входные данные описывают конкретное открытие: выбранную карту, режим, фильтр таблицы лидеров или данные для экрана результатов.
Для открытия используется Service_GameFlow.Open<T>(source, openParams). Аргумент source сообщает, откуда пришёл запрос, и помогает определить место нового состояния в иерархии. Для состояний с собственным набором параметров можно определить Opener — типизированный интерфейс открытия.
// Window_Settings — класс состояния в проекте.
this.GetService<Service_GameFlow>()
.Open<Window_Settings>(this);
В более крупном проекте такой вызов удобно спрятать за GameFacade: например, Game.UI.Settings.Open(). Это API конкретной игры; оно не появляется автоматически из одного подключения пакета.
Закрытие и повторное использование
Close() закрывает состояние в графе, сохраняя GameObject для следующего открытия. CloseAndDestroy() закрывает его с уничтожением объекта. Поэтому нельзя рассчитывать, что при каждом открытии заново выполнится Awake: входные данные и временную работу нужно обслуживать через lifecycle состояния.
Состояние может возвращать результат. Например, окно подтверждения возвращает решение, а Battle Stage — исход боя. Для состояния, реализующего IStateWithResult<T>, узел предоставляет WaitResultOnHide<T>() и WaitResultOnClose<T>(). Точку ожидания выбирают по смыслу: скрытие и логическое закрытие — разные события.
3. Иерархия и история — две разные связи
FlowGraph хранит открытые состояния, начиная с корня. У каждого FlowNode есть родитель, дочерние узлы, соседи и ссылки Back/Forward. Родитель определяет, кому принадлежит состояние. История определяет, куда вернётся пользователь.
Например, Settings может принадлежать Meta Stage, но быть открытым из MainMenu или из Shop. Вложенность остаётся той же, а путь назад различается. Попытка возврата проходит через TryGoBack; состояние может переопределить её обработку.
Один префаб State не равен одному открытию. Один и тот же Leaderboard можно открыть с разными фильтрами в разных точках истории. FlowNode хранит OpenParams, StateData и UserData конкретного открытия, тогда как экземпляр State может переиспользоваться.
Для проверки состояния доступны IsOpened, IsShowing и IsOpenedAndShowing. Они отвечают на разные вопросы: узел ещё находится в графе или его представление действительно сейчас показано.
4. Логический и визуальный жизненный цикл
Состояние может логически открыться раньше, чем появится на экране. Оно может уйти назад в истории, временно скрыться и позднее снова показаться. Поэтому GameFlow разделяет логические и визуальные callbacks.
| Изменение | Логический callback | Визуальный callback |
|---|---|---|
| Открытие | OnOpen | OnShow при первом показе этого открытия |
| Переход вперёд | OnForward | OnFwdHide при скрытии предыдущего состояния |
| Возврат назад | OnBack | OnBackShow при повторном показе |
| Закрытие | OnClosing | OnHide при скрытии закрываемого состояния |
Логические события образуют согласованные пары. Визуальные события не обязаны проходить симметричный путь: состояние могло показаться, затем скрыться при движении вперёд, а после этого уничтожиться вместе со всей веткой. Повторного визуального показа перед закрытием не будет.
Имена hooks зависят от версии: например, галерея Pro показывает OnClose и OnForwardHide там, где сохранённый Scripting API использует OnClosing и OnFwdHide. При реализации нужно сверять сигнатуры с установленным пакетом. Само разделение логических и визуальных событий остаётся тем же.
Для родительского состояния есть отдельные hooks OnChildOpen, OnChildShow, OnChildClose и OnChildHide. В Pro доступны дополнительные логические hooks и точные точки ожидания логических и визуальных изменений.
5. GameStage и принадлежащий ему контекст
GameStage — большой State уровня Boot, Meta или Core. Он создаётся дочерним узлом корня графа, а его GameObject по умолчанию живёт в DontDestroyOnLoad. У этапа есть собственный GameContext, основной контейнер состояний и контейнер popups. Поле Main State Ref позволяет указать главное состояние, открываемое автоматически.
GameContext задаёт окружение: доступные сервисы и их время жизни. GameStage управляет большим этапом, который использует это окружение. Для боя это могут быть игровые состояния, сцены карты, данные режима и ресурсы матча.
В документации пакета контекст нового этапа наследует окружение предыдущего. При этом сами GameStages находятся под корнем FlowGraph. Дерево состояний и цепочка контекстов описывают разные отношения, поэтому их не стоит автоматически считать одним и тем же деревом.
Когда бой завершён, CloseAndDestroy() этапа закрывает его состояния и завершает принадлежащий ему scope. Для следующего боя создаётся новый этап. Это работает при соблюдении владения: сцены и ресурсы должны быть привязаны к этому этапу или контексту, а созданные вручную внешние объекты требуют своей очистки.
MoveToLoadedScene переносит объект этапа в загруженную сцену, а MoveToServiceScene возвращает его в служебную сцену. Это полезно при работе с окружением карты и перед её выгрузкой.
6. Как исполняется переход
Запрос Open меняет логический граф. Затем ближайший TransitionHost получает запрос на визуальный переход. В нём различаются TipNode — логически последний узел — и ActiveNode — фактически показанное состояние.
Один host исполняет один переход за раз. Если в одном кадре несколько callbacks изменили граф, не нужно немедленно запускать анимацию для каждого промежуточного состояния. Исполнитель согласует показанное состояние с итоговой логической целью. Это не означает, что каждый вызов Open обязательно превратится в отдельный видимый экран.
По описанию механики GameFlow визуальное исполнение вынесено к концу Update. Так логические изменения и визуальная смена режима не смешиваются в случайную последовательность действий из разных callbacks.
StateTransition
Политика перехода определяет, что скрыть, что показать и в каком порядке. В API для этого предусмотрены PlanFullHide, PlanNormal, ExecutePlan, HideAsync и ShowAsync. Для типового исполнения есть HideStateListAsync и ShowStateListAsync.
В простом случае переход мгновенно переключает состояния. В Pro можно определить собственное планирование и асинхронное исполнение: закрыть старый UI, показать затемнение, дождаться загрузки и открыть новый экран. Пакет предоставляет механизм и точки расширения; конкретную анимацию создаёт проект.
Loader можно разместить на GameStage и показывать на время его открытия. Если загрузчик должен закрывать смену сразу двух крупных этапов, в Pro удобно управлять им на корневом переходе.
Когда продолжать выполнение
WaitShow, WaitHide и WaitClose позволяют ждать нужной точки жизненного цикла узла. Если следующий шаг требует готового экрана, ждать только логического открытия недостаточно. Если нужен окончательный результат сценария, скрытие окна тоже не всегда означает его завершение.
7. Подсостояния, слои и блокировка
Вкладки магазина удобно сделать подсостояниями Shop. Сам Shop управляет переключением вкладок, а каждая вкладка реализует собственное поведение и может разрабатываться отдельно. MainSubStateRef и OpenMainSubState задают основной вход, CloseSubStates закрывает вложенную ветку.
Слои позволяют одновременно держать основной экран и независимый popup. Типовой GameStage имеет Base и Popups. По умолчанию на слое одно активное состояние, но политика StateTransition может задавать другие правила. Подсостояния и пользовательские слои относятся к возможностям Pro.
Интерфейс ISubStates задаёт поддерживаемые слои, создание и уничтожение дочерних состояний. Он также участвует в кэшировании и предварительной загрузке: Preload, PreloadAsync, PreloadLibrary и ClearStatesCache.

Пауза в сетевой игре
Игрок открыл Pause, затем Settings. В это время матч продолжается и Play логически сменяется на Killed. Принудительно закрывать настройки из-за этого не нужно. TransitionHost.LockOn в Pro удерживает пользовательскую ветку, а внешние запросы меняют историю под заблокированным состоянием. После выхода из меню игрок возвращается к актуальному состоянию матча.
Locking защищает навигацию; остановку симуляции, времени или сети нужно реализовать отдельно. Для независимых переходов нескольких игроков можно использовать отдельные hosts. В старой документации создание такого исполнителя на узле называется SpawnTransitionRoot.
8. Сцены, ссылки и переходы между картами
Для ссылок на состояния и сцены GameFlow использует Flexy.AssetRefs. StateRef и SceneRef позволяют связывать assets без строковых имён сцен и жёстких ссылок из случайных менеджеров. Состояние управляет загрузкой, а Unity SceneManager выполняет её под капотом.
Пакет поддерживает Single и Additive. Если одновременно нужна одна карта, не стоит вводить аддитивную композицию только ради архитектуры. Additive полезен, когда несколько сцен действительно должны жить вместе. В документации Pro также описаны SubScenes и SceneSets для составных сцен и загрузки заранее заданного набора.
Загружаемая сцена регистрируется в GameContext до выполнения её Awake. Поэтому объекты сцены могут получить подготовленное окружение сразу при запуске. Это связывает управление сценами с порядком инициализации контекстов.
CrossSceneRef
Для связи объектов разных сцен предусмотрены CrossSceneRef и сериализуемый CrossSceneRef<T>. Компонент хранит идентификатор объекта внутри сцены, ссылка — сцену и идентификатор цели. Get<T> получает компонент или сообщает об ошибке, Find<T> возвращает null, если цель недоступна.
MapPortal и Service_MapTransitions
Готовый пример связывает три части: CallBinder_TriggerEnter реагирует на вход нужного коллайдера, MapPortal хранит точку входа и ссылку на портал другой карты, а Service_MapTransitions исполняет переход.
FadeOutзакрывает экран overlay.StorePersistentObjectsпереносит сохраняемые объекты в DontDestroyOnLoad.LoadMapменяет карту.RestorePersistentObjectsвозвращает объекты в новую сцену и точку входа.FadeInубирает overlay.
В примере доступны Single, Additive и режим AdditiveNoUnload. Портал и сервис переходов — отправная точка для адаптации под проект: политика сохранения игрока, положение после перехода и загрузочная анимация остаются решениями конкретной игры.
9. Запуск с любой сцены
GameFlowBootstrap создаёт Service_GameFlow, стартовый GameStage и указанные дополнительные состояния. Поле Target State задаёт конечное состояние запуска и источник TestCases. Компоненты на bootstrap-префабе добавляются в глобальный контекст, что позволяет настраивать окружение тестовых сцен.
Корневой сервис получает Root Flow Library и необязательную Back Input Action. Библиотеки можно разделить на Root, Common, Boot, Meta и Core. У FlowLibrary есть режим автоматического сбора из текущей папки, из вложенных папок или ручной режим; поле Dependencies связывает библиотеки.

Bootstrap помещают в каждую сцену, с которой нужно входить в Play Mode. Он восстанавливает нужную иерархию на старте, до обычной логики сцены. Так тестовая сцена и запуск через главное меню используют одну модель контекстов и состояний.
Созданный префаб состояния попадает в FlowLibrary при включённом автоматическом сборе. Узел FlowGraph создаётся позднее, при фактическом открытии. Это разные этапы: наличие префаба в библиотеке ещё не означает, что состояние открыто в игре.
10. Как добавить состояние в проект
- Создайте класс от
Stateи задайте его ответственность: какие действия доступны игроку и какими системами управляет это состояние. - Соберите префаб с представлением и компонентом State. Для UI можно использовать подход MC-VmV.
- Поместите префаб в библиотеку своего этапа или проверьте, что его подхватил автоматический сбор.
- Определите входные параметры, результат и типизированный Opener, если он нужен.
- Реализуйте lifecycle: получение данных, запуск работы, показ, скрытие и завершение.
- Создайте TestScene с Bootstrap и Target State. Задайте сценарии через TestCases.
- Подключите открытие состояния из существующего flow через Service_GameFlow или GameFacade.
!Game/Flow/
├── Bootstrap
├── RootLibrary / CommonLibrary
├── Boot/
│ └── Stage, Library, States, TestScenes
├── Menu/
│ └── Stage, Library, MainMenu, Settings, Shop, TestScenes
└── Play/
└── Stage, Library, Play, Pause, Results, TestScenes
!Game/Maps/ · сцены игровых карт
!Game/!Code/ · код состояний и игровые системы
Такая структура из книги группирует flow по этапам. Меню и gameplay могут иметь свои фасады и базовые классы состояний, чтобы код обращался к сервисам своего окружения.
11. Разработка и тестирование в изоляции
Чтобы проверить экран наград, не нужно проходить весь бой. В TestScene можно сразу открыть Results с подготовленным результатом. Чтобы проверить бой с боссом, можно начать с нужной фазы и заданного состояния игрока.

TestCases описывают такие входные ситуации: мало здоровья, определённая экипировка, конкретная карта, набор наград или начало катсцены. Они сокращают ручную подготовку и делают проблему воспроизводимой.

Изолированный запуск — способ разработки, а не замена проверок всего сценария. Отдельно полезно проверять переходы вперёд и назад, смену этапа во время загрузки, завершение боя и очистку принадлежащих ему ресурсов.
Для State важны четыре практических вопроса: открывается ли он с нужными параметрами, получает ли правильный контекст, корректно ли возвращает результат и завершает ли свою работу при закрытии. Удобство такого тестирования напрямую зависит от того, насколько явно определены границы состояния.
12. Как это складывается в игровую сессию
Boot → Meta → Core
Bootstrap поднимает корень и Boot. Boot выполняет подготовку: соглашения, согласия, профиль, конфиги и загрузку ресурсов. После готовности открывается Meta с MainMenu. Игрок выбирает карту, и flow открывает Core с параметрами карты и режима.
Core подготавливает контекст, загружает карту и показывает Play с HUD. Play управляет вводом и игровыми системами. Пауза, катсцена или NPC-диалог меняют доступные действия через отдельные состояния. По окончании матча открывается Results, затем этап закрывается и возвращает результат вызывающему сценарию.
В документации этот сценарий выражен как await Game.Flow.OpenBattle(map, mode). Это пример API фасада проекта: конкретные типы параметров, результата и способ открытия Battle Stage определяются самой игрой.
Магазин с вкладками
Shop владеет локальной навигацией между вкладками. Каждая вкладка получает свои данные и самостоятельно показывает товары. Общий экран отвечает за переключение и анимацию, а не содержит все варианты поведения в одном большом условии.
Split-screen
Каждому игроку можно дать отдельный GameStage, контекст и TransitionHost. Тогда его HUD, камера, ввод и локальные окна работают в своём окружении. Открытие Killcam для одного игрока не обязано переключать представление второго. Общие данные матча при этом остаются на общем уровне.
Перезапуск
Service_GameFlow.Reboot закрывает узлы до корня, уничтожает состояния и заново открывает первый или указанный этап. Для загрузки другого профиля или полного повторного входа это позволяет пересоздать flow вместо ручного сброса флагов во всех окнах.
13. Что даёт пакет и что добавляет Pro
Flexy.GameFlow реализует описанную модель для Unity: иерархию состояний, граф навигации, историю, загрузку сцен, контексты этапов и запуск состояний в изоляции. Он использует Flexy.Core и Flexy.AssetRefs; на странице Pro указано, что зависимости включены в поставку.
На странице Flexy.GameFlow Pro в Unity Asset Store к возможностям Pro отнесены:
- пользовательские слои и подсостояния;
- блокировка состояния, полезная для сетевой игры;
- собственная логика переходов;
- SpawnTarget для выбора точки открытия в графе;
- логические callbacks Open/Close и Forward/Back;
- точные точки ожидания логических и визуальных изменений;
- асинхронная предварительная загрузка представлений;
- перезапуск всего игрового flow или возврат к первому этапу.
Дополнительно документация описывает SubScenes, SceneSets и расширение кэширования состояний. При выборе версии стоит сверять её API и комплект поставки с актуальной документацией.
GameFlow особенно полезен игре с меню, несколькими этапами, вложенными экранами и асинхронными переходами. Для небольшой игры с одной сценой такая модель может оказаться избыточной. Здесь требуется C# и осмысленная декомпозиция: редактор визуальных графов и готовый UI-конструктор в эту задачу не входят.
По описанию магазина архитектура развивается в production-проектах с 2014 года.
14. Документация и рабочие примеры
Для первого знакомства документация предлагает импортировать FlowSampleURP.unitypackage из пакета, при необходимости установить TMP Essential Resources, открыть Boot-сцену примера и запустить Play Mode. Для подробного изучения доступны шаблоны с полным flow.
- Обзор Flexy.GameFlow и подробное описание пакета.
- Start Guide и How It Works & Use Cases.
- Scripting API: State, GameStage, FlowGraph, FlowNode, TransitionHost, StateTransition, библиотеки, bootstrap, cross-scene ссылки и переходы между картами.
- Barley-Break: шаблон с Pro flow и GameFlow Minimal Showcase.
- Исходники Lite и обсуждение и вопросы.