2016-08-27 2 views
0

Я хотел бы использовать машину конечного состояния для обработки Entity состояний в моей игре. В частности, для этой публикации я собираюсь обратиться к объекту Player.Выполнение конечного состояния машины в системе компонентов объекта

Мое Player будет иметь такие состояния, как холостой ход, бег, прыжки, падение и т. Д. ... и нужно каким-то образом управлять этими состояниями и переходами между ними. В среде ООП самым простым решением было сделать каждое состояние своим собственным классом и иметь метод, называемый handleInput, принимать входные данные и определять, должно ли происходить изменение состояния. Например, в IdleState, если произошло движение move_right или move_left, состояние изменится на новый RunningState. Это легко и имеет смысл, потому что поведение состояния должно быть инкапсулировано в состояние.

Однако все меняется, когда вы используете FSM в системе компонентов сущности. Государства перестали быть объектами (потому что это противоречило бы гибкости системы компонентов), а вместо этого - различные компоновки компонентов. JumpState может иметь компоненты, такие как JumpComponent, AirbornMovementComponent и т.д ... в то время как AttackState может иметь компоненты, представляющие собой атаку, как SwingComponent, DamageComponent, SwordComponent и т.д ... Идея состоит в том, перестраивая компоненты, новые состояния могут быть созданы. Задача систем состоит в том, чтобы просто обрабатывать эти компоненты отдельно, потому что системы не заботятся о состоянии, они заботятся только об отдельных компонентах. Фактический FSM находится в FSMComponent, принадлежащем сущности.

Это имеет большой смысл, за исключением случаев, когда дело касается обработки переходов состояния. Прямо сейчас у меня есть InputSystem, который ищет объекты, которые имеют InputComponent и FSMComponent, и пытается обновить состояние FSM на основе текущего ввода. Однако это не работает так хорошо.

Лучший способ (на мой взгляд) для FSM обрабатывать входные данные состоит в том, чтобы каждое состояние определяло, как он хочет обрабатывать ввод и как перейти на новое состояние на основе этого ввода. Это относится к способу внедрения FSM в OOP, противоречащему дизайну ECS, где компоненты - это просто пакеты данных и системы, которые выполняют всю логику. В ECS идея заключалась бы в том, чтобы переходы состояния системы обрабатывались, но это осложняется тем, что каждый FSM может иметь разные условия для перехода между состояниями.

Вы не можете просто указать в InputSystem «если вход должен двигаться вправо, а затем установить состояние в состояние». Это было бы специфично для игрока, но может быть недействительным для ВСЕ объектов. Если в один прекрасный день я решит сделать врага управляемым, входы, которые работают для Player, не будут одинаковыми входами для Enemy.

Мой вопрос: Как я могу позволить моему FSM быть достаточно общим и достаточно гибким в ECS, чтобы допускать различные реализации переходов состояний без необходимости делать явные проверки if/else в самих системах?

Я подхожу к этому совершенно неправильно? Если да, то какое лучшее решение для внедрения FSM в системе компонентов сущностей?

+0

У пепловой рамки есть довольно интересный подход, есть запись, в которой автор пишет об этом здесь: http://www.richardlord.net/blog/finite-state-machines-with-ash. Он также получил исходный код здесь: https://github.com/richardlord/Ash/tree/master/src/ash/fsm – fallaciousreasoning

ответ

0

Каркас ясеня имеет довольно интересный подход, автор пишет об этом here

Он принимает подобный подход к тому, что ты предполагая, утверждая, что состояние хозяйствующего субъекта зависит от компонентов, которые делают его (которые, в свою очередь, определяют, какие системы обрабатывают сущность).

Чтобы упростить управление переходами состояний, он вводит класс FiniteStateMachine, который отслеживает, какие компоненты необходимы для того, чтобы объект находился в разных состояниях.

Например, враг ИИ может быть в состоянии патрульного, если он имеет компонент Transform и Patrol, поэтому он будет регистрировать эту информацию с FiniteStateMachine

var fsm = new FiniteStateMachine(enemyEntity); 

fsm.CreateState("patrol") 
    .WithComponent(new Transform()) 
    .WithComponent(new Patrol()); 

Когда конечный автомат велят изменения состояние объекта, оно удаляет и добавляет компоненты для перехода в желаемое состояние. Любая система, которая должна изменить состояние объекта, просто нуждается в ссылке на конечный автомат (что-то вроде fsm.ChangeState("patrol")).

Он также выпустил исходный код для него, который вы можете найти here (он также объясняет это лучше, чем я когда-либо мог) и есть практический пример в базовой игре астероидов here. Код в ActionScript (я думаю), но вы должны иметь возможность расшифровать его без особых трудностей.

+0

Это не работает. Позволь мне объяснить. Что делать, если вы решите, что вы хотите, чтобы игрок работал, когда используются входы для перемещения влево и вправо. Затем вы можете опросить вход и изменить состояние на основе этих значений. Теперь вы решаете, хотите ли вы иметь состояние, в котором игрок заморожен и не может двигаться. Внезапно вы перерывы FSM, потому что теперь вы можете работать в состоянии, в котором вы не должны запускаться. Переходы являются специфичными для штата и не должны определяться в рамках системы. –

+0

В этом случае не удалялся бы компонент запуска, который остановил бы сущность, обрабатываемую RunSystem, по сути, замораживая ее? Я просто рассматриваю эту проблему самостоятельно, так как я начал разрабатывать собственную систему ECS, поэтому я довольно далек от эксперта. – fallaciousreasoning

+0

Я создал гораздо более надежную систему, которая позволяет вам определять переходы. Затем у меня есть системы перехода, которые обрабатывают все сущности в состоянии, которое имеет эти переходы, и если требования перехода выполнены, сущность меняет состояния. –

0

Просто рифферуйте сообщение @ fallaciousreasoning (и его последующие комментарии).

Пепел фактически имеет два FSM, которые работают на разных уровнях.

Во-первых, существует FSM, работающий на уровне Entity, который управляет переходами (сущностью), изменяя состав компонентов на сущности при переходе из одного состояния в другое.

И, во-вторых, есть FSM, работающий на уровне двигателя, который управляет переходом состояния двигателя, изменяя состав систем, выполняемых двигателем.

В сочетании они делают для довольно надежного FSM.

Фокус в том, чтобы определить, с каким типом перехода необходимо работать; где композиция «данных» управляет переходами, или одна, где «логическая» композиция управляет переходами.

Так вооруженный этим новым найденным знанием позволяет понять, как это будет работать.

В более наивных подходах к изменению состава компонентов мы будем использовать ряд компонентов «тегов», а также некоторые длинные операторы switch (или проверки if/else) для обработки этих изменений в состоянии сущности, что в конечном итоге приводит к раздуванию Системы, которые делают больше, чем должны. Ash's Entity FSM уточняет это и избегает этих длинных операторов switch (или if/else clause), сопоставляя заданную конфигурацию компонента с идентификатором и предоставляя менеджер, который может использоваться для запуска переходов состояний. Этот экземпляр менеджера может передаваться как свойство внутри компонента или его можно составить/ввести как член системы.

В качестве альтернативы, принимая подход FSM Engine, мы разбиваем каждый бит логики состояния на свои собственные Системы и свопим их в исходное состояние (исходящее). Этот метод не лишен недостатков, поскольку отсутствие системы повлияет на все связанные с ней объекты.Тем не менее, не редкость иметь системы, предназначенные для одного экземпляра объекта (например, персонажа игрока), поэтому это может оказаться полезным в правильном контексте. Подумайте, что это может повлиять на сущности во всем мире через системные свопы.

() Примечание. Если объем вашей логической модификации должен быть более узким, вы можете ограничить его Системой, не используя систему FMS Engine. Этого можно достичь, внедряя шаблон состояния в Системе, в которой система может изменить его поведение путем делегирования в разные подсистемы на основе состояния.)

Я видел некоторые маркировки ECS Системные композиции как «Фазы», ​​но они в основном действуют как FSM, где ECS-движок обрабатывает объекты с использованием разных наборов систем, связанных с данной фазой.

В заключение состав данных составляет лишь половину уравнения; как вы составляете свои биты (или блоки) логики, так же важно при попытке внедрить FSM в ECS.