Я работал на том же движке, что и Coderanger. У меня другая точка зрения. :)
Во-первых, у нас не было стека автоматов - у нас был стек состояний. Стек состояний составляет один FSM. Я не знаю, как будет выглядеть стек автоматов. Вероятно, слишком сложно, чтобы сделать что-нибудь практическое с.
Моя самая большая проблема с нашим Global State Machine состояла в том, что это был набор состояний, а не набор состояний. Это означает, например, ... / MainMenu / Загрузка отличалась от ... / Загрузка / MainMenu, в зависимости от того, открылось ли главное меню до или после экрана загрузки (игра асинхронная и загрузка в основном выполняется сервером ).
В качестве двух примеров вещей это сделало безобразным:
- Это привело, например, к состоянию LoadingGameplay, поэтому у вас были Base / Loading и Base / Gameplay / LoadingGameplay для загрузки в состоянии Gameplay, которое должно было повторять большую часть кода в нормальном состоянии загрузки (но не все, и добавить еще несколько). ).
- У нас было несколько функций, таких как «если в создателе персонажа перейти к игровому процессу; если в игровом процессе перейти к выбору персонажа; если в выборе персонажа вернуться к входу в систему», потому что мы хотели показать одинаковые интерфейсные окна в разных состояниях, но сделать Назад / Вперед кнопки все еще работают.
Несмотря на название, оно было не очень «глобальным». Большинство внутренних игровых систем не использовали его для отслеживания своих внутренних состояний, потому что они не хотели, чтобы их состояния были испорчены другими системами. Другие, например система пользовательского интерфейса, могут использовать ее, но только для копирования состояния в свои собственные локальные системы состояний. (Я бы особенно предостерегал против системы для состояний пользовательского интерфейса. Состояние пользовательского интерфейса - это не стек, а действительно DAG, и попытка навязать ему любую другую структуру приведет только к тому, что пользовательские интерфейсы будут разочаровывать.)
Для этого было полезно изолировать задачи для интеграции кода от инфраструктурных программистов, которые не знали, как на самом деле структурирован игровой процесс, чтобы вы могли сказать парню, пишущему патчер, «поместить свой код в Client_Patch_Update», а парню, пишущему графику. загрузка «поместите ваш код в Client_MapTransfer_OnEnter», и мы могли бы без особых проблем поменять местами определенные логические потоки.
В стороннем проекте мне больше повезло с набором состояний, а не со стеком , не боясь создавать несколько машин для несвязанных систем и не позволяя себе попасть в ловушку «глобального состояния», которое действительно просто сложный способ синхронизировать вещи через глобальные переменные - конечно, вы в конечном итоге сделаете это в какой-то крайний срок, но не замышляйте это как свою цель . По сути, состояние в игре не является стеком, и состояния в игре не все связаны между собой.
GSM также, как обычно делают указатели функций и нелокальное поведение, усложнял отладку, хотя отладка такого рода больших переходов между состояниями была не очень забавной, пока мы ее не сделали. Наборы состояний вместо стеков состояний на самом деле не помогают, но вы должны знать об этом. Виртуальные функции, а не указатели на функции могут несколько смягчить это.