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