Unityのシンプルなステートマシン

開発中に、できればすでに実装されている単純な状態マシンが必要でした。 Googleが提案した実装のリストから、これはシンプルさとコンパクトさのために選択されました。 私たちはそれを自分で使用します。一般に、FSMは悪くありません。 さらにカットされているのは、ギリシア・タソス・ジャンナコポウロスの著者によるオリジナル記事の翻訳です。 私は翻訳者ではないので、その意味を伝えようとしましたが、時には自分の言葉でその本質を説明し、完璧主義者に謝罪しました。



ステートマシンとは


ステートマシンは、ゲーム開発者が動作(たとえば、ユニットまたはいくつかの複雑なオブジェクトの動作)を実装するために使用する一般的なデザインパターンです。

ステートマシン(ブルジョア用語での有限ステートマシンまたはFSM)は、図によって簡単に記述されてからプログラムされるため、さまざまな動作を実装するために使用できます。



AI-depot.comサイト(元の記事の著者によると最高のAIサイト)の定義によれば、ステートマシンは4つの主要な要素で構成されています。

-動作を決定し、アクションを生成できる条件

-ある状態から別の状態への遷移を決定する状態遷移

-移行のために満たさなければならない条件

-外部または内部から受け取った入力状態。ルールに従って、状態の遷移につながる可能性があります



私はそれを必要とする有限状態マシンの理論には立ち入りません-インターネットには詳細な記事がたくさんあり、記事の最後にいくつかのリンクがあります。



なんでこんなこと?


メインキャラクターの動作を実装するために、現在取り組んでいるプロジェクトでは、FSMを使用しました。 C#での実装。 現時点では、コードは最終的な形式にはほど遠いですが、基本的な機能を備えているため、FSMの動作原理を説明するのに十分です。



-有限状態マシンの初期化とキャラクターの動作を決定する一連の遷移

-入力イベントが到着すると、FSMを適切な状態にする試みが行われます

-遷移が可能な場合、状態が変化し、対応する遷移に対してコールバックが呼び出されます



一般的に、プレイヤーのキャラクターの動作を決定する次のスキームを実装できるものが必要でした。 さらに、システムを拡張可能にして、新しい状態と遷移を簡単に追加できるようにしたいと思います。







設計と実装


私は、C#でこのタスクをデリゲートの助けを借りて解決するのが最適であると考え、考え、決定しました。 C#のデリゲートは関数へのポインタであり、どこからでも関数を呼び出すことができます。 使いやすく、柔軟性があり、最も重要なのは、すばやく動作することです(これはほとんど直接的な関数呼び出しです)。







上記のクラス図では、実際のステートマシンインターフェイスであるIEquatableおよびFiniteStateMachineインターフェイスを介して実装されたStateTransitionを見ることができます。 両方のクラスは、ユーザーが状態を判断できるテンプレートです。 それらを列挙で使用します。これにより、可能な状態のリストを定義できます。



StateTransitionは基本的にC#タプルであり、2つの状態の値がキーとして生成されます。 既に実装した後、簡単にできることを見つけました-System.Collections.Generic.KeyValuePair <K、V>を使用して実装します。KとVは可能な状態です。 しかし、タプルからKeyValuePairに切り替えると速度が向上するかどうかわからないので、そのままにしておくことにしました。



記事の最後に、私の実装のソースへのリンクがあります。 解凍して、次の例のように使用します。 FSMは完全にはほど遠いということは既に述べましたが、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



All Articles