Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Примитивный финальный автомат на Unity

Anna | 17.06.2014 | нет комментариев
При разработке нам потребовался примитивный финальный автомат, желанно теснее реализованный. Из списка реализаций, тот, что предложил гугл, предпочли данный, за простоту и компактность. Используем у себя, в целом FSM недурен. Дальше под катом перевод подлинной статьи автора из Греции Tasos Giannakopoulos. Я не переводчик, следственно я усердствовал передать толк, изредка поясняя суть своими словами, за что извиняюсь перед перфекционистами.

Что такое Финальный автомат?

Финальный автомат является знаменитым образцом проектирования, тот, что применяются разработчиками игр для реализации поведения, к примеру поведения юнитов либо каких-то трудных объектов.
Финальный автомат (Finite state machine либо FSM в буржуйской терминологии) легко описывается диаграммами и потом программируется, что разрешает применять его для реализации широкого круга поведений.

По определению сайта AI-depot.com (наилучший сайт по AI по суждению автора подлинной статьи), финальный автомат состоит из четырёх основных элементов:
— состояний, которые определяют поведение и могут изготавливать действия
— переходов состояний, которые определяют переход от одного состояния к иному
— правил и данные, которые обязаны быть выолнены для перехода
— входных состояний, полученных извне либо изнутри, которые могут согласно правилам привести к переходу состояний

Я не буду вдаваться в теорию финальных автоматов, кому нужно — есть интернет с кучей подробных статей, а так же есть несколько ссылок в конце статьи.

Для чего всё это?

Дабы реализовать поведение основного героя, в плане над которым я теперь тружусь, я применял FSM. Реализация на C#. На данный момент код далёк от своего финального вида, но имеет базовый функционал, чего довольно для объяснения правила работы FSM.

— Инициализация финального автомата и комплекта переходов, определяющего поведение персонажа
— Когда приходят события ввода, делается попытка перевести FSM в соответсвующее состояние
— Если переход допустим, то состояние меняется и вызывается callback для соотсветсвующего перехода

В всеобщем, я хотел что-то, что дозволит мне реализовать следующую схему, определяющую поведение персонажа игрока. Помимо того, хотелось бы, Дабы система была расширямой и дозволено было легко добавить новые состояния и переходы.

Проектирование и реализация

Я здесь посмотрел, подумал, и решил что на C# эту задачу отменнее решать с поддержкой делегатов. Делегаты в C# — это указатели на функции, что разрешает вызвать функцию из всякого места. Они примитивные в применении, эластичные, а основное стремительно работают (это примерно что прямой вызов функции).

В диаграмме классов выше вы можете увидеть StateTransition которые реализуется через интерфейс IEquatable и FiniteStateMachine, собственно сам интерфейс финального автомата. Оба класса представляют собой образцы, разрешающие пользователю определять состояние. Я использую их с перечислениями (enums), которые разрешают определить список допустимых состояний.

StateTransition по сути это C# кортеж (tuple), где в качестве ключа генерится значение по двум состояниям. Позже того, как я теснее реализовал, я узнал что дозволено сделать проще — реализовать через System.Collections.Generic.KeyValuePair<K, V>, где K и V — допустимые состояния. Но так как я не уверен что переход с кортежа на KeyValuePair даст приход скорости, решил оставить всё как есть.

В конце статьи вы найдёте ссылку на исходники моей реализации. Легко распакуйте, и используйте, как в примере, приведённом ниже. Я теснее говорил, что FSM далека от заключения, но она обеспечивает базовую функциональность, и может быть отправной точкой для других планов.

Как применять

Для начала сделайте перечислиние всех состояний вашего объекта и передайте их в FiniteStateMachine.

// Add the possible states here
public enum eCharacterState
{
  IDLE,
  RUN,
  // ...
};

public class CharacterFSM : FiniteStateMachine<eCharacterState> {};

Вы обязаны сделать кучу функций, которые реализуют поведение вашего объекта, у меня к примеру это Run(), Idle(), IdleJump() и другие. После этого с поддержкой AddTransition() добавьте желаемые переходы между состояниями. При соблюдении определённых условий, вы вызываете Advance() для того, Дабы попытаься переключиться в надобное состояние. Если переход из нынешнего состояние допустим, то вызывается функция, определённая пользователем.

Приведённый ниже код реализует часть поведения моего персонажа. Этого фрагмента кода довольно для понимания, как применять FSM.

public class Player : CatGameItem
{
  // ...
  public  CharacterFSM mFSM;

 void Start () 
  {
    mFSM =  new CharacterFSM();

    // Add state transitions here
    mFSM.AddTransition(eCharacterState.IDLE,        eCharacterState.RUN,         Run);
    mFSM.AddTransition(eCharacterState.RUN,         eCharacterState.IDLE,        Idle);

    // This calls the Run() function while on run state. 
    // I will probably replace it with with a state callback or something similar sometime in the future to avoid calling TryGetValue all the time.
    mFSM.AddTransition(eCharacterState.RUN,         eCharacterState.RUN,         Run);
    // ...
  }

  // FSM Delegates
  void Run()
  {
    //Debug.Log("RUN!");
    float curMoveSpeed = Controller.GetGroundSpeed();
    AnimationController.SetSpeed("Cat_Run", curMoveSpeed/RunSpeed);
    AnimationController.Play("Cat_Run");
  }

  void Idle()
  {
    AnimationController.Play("Cat_Idle_Breath");
  }

  // ...

  void UpdateInput()
  {
    mCurAxisInput.x = Input.GetAxis("LeftAxisH");   // Get Horizontal axis (XBox360 xAxis OR 'A', 'D')
    mCurAxisInput.y = Input.GetAxis("LeftAxisV");   // Get Vertical axis (XBox360 yAxis OR 'W', 'S')
  }

  void UpdateStateMachine()
  {
    // Based on the input events, advance to desired state
    // Run, Idle 
    if (mCurAxisInput.magnitude > 0)
      mFSM.Advance(eCharacterState.RUN);
    else
      mFSM.Advance(eCharacterState.IDLE);
    // ...
  }

  void FixedUpdate()
  {
    // Update the state machine here
    UpdateStateMachine();
  }

  void Update () 
  {
    // Update user input
    UpdateInput();
    UpdateCharacterMovement();
 }
}

Исходник FSM

Ссылки на статьи по теме:

https://en.wikipedia.org/wiki/Finite-state_machine
http://ai-depot.com/FiniteStateMachines/FSM.html
http://jessewarden.com/2012/07/finite-state-machines-in-game-development.html
http://unitygems.com/fsm2/

Автор подлинной статьи: Tasos Giannakopoulos.

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB