はじめに


「Arbor: State Diagram Editor」について

  • Unityで有限ステートマシンを使ってゲーム作りたい!
  • だけど、ゲームロジックに依存する挙動は自分でコーディングしたい!
  • そんな時に使えそうな有限ステートマシンの編集ウィンドウと、
    作りたい挙動にあわせてステートのスクリプトを書けるシンプルなステートマシンアセットです。

そもそも有限ステートマシン(FSM)って何?

  • 有限ステートマシンとは、ある状態での挙動と、その状態から別の状態へ遷移する仕組みです。
  • たとえば、スイッチと電灯。
  • スイッチと電灯にはONとOFFという状態があり、スイッチをONにすれば電灯もONになります。
  • スイッチは押せばONに切り替わり、再度押すとOFFに切り替わる挙動です。
  • 電灯はONであれば明かりを灯す挙動になります。

ゲームでの使いどころ

ゲームの多くは、状態と挙動の移り変わりで表現できてしまうかと思います。
たとえば敵の動きなどは以下のようにすることがあります。

  • 「発生ステート」。
    敵が発生したら発生モーションをとる。
    モーション終了後、「パトロールステート」に遷移。
  • 「パトロールステート」。
    適当に巡回させつつどうしようか考える。
    プレイヤーが近くにいるとき、敵自身のHP高い場合は「追跡ステート」に遷移。
    HP低い場合は「逃走ステート」に遷移。
  • 「追跡ステート」。
    プレイヤーに攻撃できる位置まで移動する。
    攻撃できる位置に到着後、「攻撃ステート」に遷移。
  • 「攻撃ステート」。
    攻撃!
    攻撃モーション終了後、「パトロールステート」に戻る。
  • 「逃走ステート」。
    見つかったプレイヤーから逃げる。
    遠くまで離れたら安心して「パトロールステート」に戻る。

この例では、追跡するか逃亡するかを自分のHPで分岐しています。
たった1箇所での分岐ですが、文章にしてみるとどこでどう繋がっているかすぐには分かりませんね。
ラスボスのような複雑な動きをする場合は状態も挙動も複雑化して、さらに複数のステートマシンが連動する可能性もありえます。
ある時はパトロール、ある時は逃亡、という挙動を細かくスクリプトに、
あとはエディタで遷移の関係を編集する形にしたほうが視覚性が良くなり開発効率も向上するかと思います。

Arborを使えば、このように視覚的に状態の遷移を組むことができます。

Arborを入手する

Arborを使用するための準備

プロジェクト作成

Arborを使用するプロジェクトがまだない場合は新規に作成する必要があります。

プロジェクトの作成方法についての詳細はUnity ManualのGetting startedを参照してください。

「Asset packages」ボタンからArbor 2を選択することで後で行うインポート作業を省略できます。

リストにArbor 2パッケージが見つからない場合は後述の「Arborのインポート」を参照してください。

最後に「Create Project」ボタンを押してプロジェクトを作成します。

Arborのインポート

「プロジェクト作成」にてArbor 2パッケージを入れなかった場合や、すでにあるプロジェクトにArborをインポートする際にこの作業が必要になります。

Arborをインポートするために、まずAssetStoreウィンドウを表示します。

メニューから、「Window > Asset Store」を選択するか、ショートカットのCtrl + 9を押してください。

AssetStoreウィンドウが表示されたらツールバーのToggle Download ManagerアイコンをクリックしDownload Managerに切り替えます。

表示されるアセット数が多く、Arbor 2パッケージがすぐに見つけられない方はフィルターを使用してください。

Group byを「Title」、Filterに「Arbor 2」にしFilterボタンを押すと絞り込めます。

Arbor 2のImportボタンをクリックするとImport Unity Packageウィンドウが表示されます。

ImportボタンがなくDownloadボタンになっている場合はまだダウンロードできていませんので先にDownloadボタンをクリックしてください。

ウィンドウ右下のImportボタンをクリックすることでインポート完了です。

使い方

ArborFSMについて

ArborFSMはArborの主軸となるコンポーネントです。

GameObjectにArborFSMを追加し、ArborEditorウィンドウでStateなどのノードを設定することでゲーム内ロジックを組めるようになります。

ArborFSMの追加

  • 適用したいGameObjectを選択
    「メニュー > Component > Arbor > ArborFSM」を選択 。
  • あるいはInspectorの「Add Componentボタン > Arbor > ArborFSM」を選択。
    GIF
  • また、HierarchyのCreateボタン「Arbor > ArborFSM」からArborFSMがアタッチされた状態のGameObjectが作成できる。
    GIF

Arbor Editorを開く

  • 編集したいArborFSMのOpen Editorボタンをクリック。
    Arbor Editorを開く(Open Editorボタンから)
    あるいは「メニュー > Window > Arbor Editor」を選択

ArborFSMの選択

  • Arbor Editor上部の選択ボックスにドラッグ&ドロップ。
    あるいは選択ボックスをクリックしてリストから選択。
    ArborFSMの選択
  • ArborFSMのInspectorでOpen Editorボタンを押した場合は自動的に選択状態になる。

ステートの作成

  • Arbor Editorの適当な位置を右クリック。
    「ステート作成」をクリック。
    GIF

ノードの名前変更

  • ノード枠内上部にあるヘッダ部分をダブルクリック、あるいは右クリックか設定アイコンから「リネーム」を選択。
    表示されたテキストボックスに入力。
    GIF

開始ステートの指定

開始ステートとは、オブジェクトがアクティブになった際、一番初めに実行されるステートです。
(開始ステートがない状態でステートを作成すると自動的に開始ステートになります)

  • ステート名横の設定アイコンをクリック。
    「開始ステートに設定」を選択。
    GIF

ノードの削除

  • 削除したいノードを選択。
  • 何もない箇所を右クリックし「削除」を選択、もしくはDeleteキーを押す。
    GIF

ステートに挙動を追加

  • ステート名横の設定アイコンをクリック。
  • 「挙動追加」を選択。
  • 挙動一覧から追加したい挙動を選択。
    GIF
  • 設定したいスクリプトファイルを直接ドラッグ&ドロップでも可。

挙動の削除

  • 挙動名横の設定アイコンをクリック。
  • 「削除」をクリック。
    GIF

遷移に関する挙動

遷移に関する挙動は初めからいくつか組み込まれています。

  • ステート名の横にある設定アイコンから「挙動追加」を選択。
    Transitionの中に各種遷移系の挙動が入っている。
    GIF
  • 時間で遷移するTimeTransitionなどがある。

挙動のマニュアルを開く

組み込み済みの挙動に関して、ヘルプアイコンをクリックすることでマニュアルページをブラウザで開きます。

  • 各種挙動のタイトルバー横にあるヘルプアイコンをクリックする

挙動からステートへ接続

  • TimeTransitionなど遷移系の挙動をあらかじめ追加しておく。
  • ステート接続エリアから他Stateにドラッグ&ドロップ。
  • 何もないところで離せば解除
    GIF

遷移ラインの右クリックメニュー

遷移ライン上を右クリックすると、遷移元と遷移先に移動するメニューが表示されます。

GIF

TransitionTimingについて

遷移するタイミングは即座に行われるのではなくTransitionTimingの指定によって変わります。

TransitionTimingは遷移スロットの設定アイコンをクリックすると開く設定ウィンドウによって行えます。

GIF

TransitionTimingの動作は以下のようになります。

Late Update Overwrite LateUpdate時に遷移するよう予約する。
同フレーム内で既に遷移予約されている場合は上書きする。
Immediate 遷移呼び出し時に瞬時に遷移する。
遷移がループしている場合、無限ループする可能性もあるので使用には注意すること。
Late Update Dont Overwrite LateUpdate時に遷移するよう予約する。
同フレーム内で既に遷移予約されている場合は上書きしない。
(Arbor2.2.0以降デフォルト)

常駐ステートについて

常駐ステートは常に動き続けるステートで、強制的に割り込ませたい処理待ち(コリジョンなど)をする際に利用します。
動き続ける代わりに他のステートからの遷移は受け付けない点に気を付けてください。

  • Arbor Editorの適当な位置を右クリック。
    「常駐ステート作成」をクリック。
    GIF

値の指定方法を選択する

  • 各プロパティのフィールド横にマークがついている場合、クリックすることで値の指定方法を選択できる。
    GIF
  • 値の種類によって選択項目は異なりますが、主にあるのは以下の通り。
    • Constant
      固定値を指定する
    • Parameter
      パラメータを参照する。
      パラメータについては後述の「ParameterContainerについて」を参照してください。
    • Random
      指定範囲の中からランダムに取得する。
    • Calculator
      演算ノードからの入力を受け付ける。
      演算ノードについては後述の「演算ノードについて」を参照してください。

演算ノードについて

演算ノードにより、変数の入出力や演算がArbor Editor上でできるようになります。

演算ノードの作成

  • Arbor Editorの適当な位置を右クリック。
  • 「演算ノード作成」をクリック。
    作成したい演算ノードをリストから選択
    GIF

演算スロットの接続

  • 入力もしくは出力スロットをドラッグ&ドロップして接続する。
    入力スロットからのドラッグ&ドロップ中に何もないところで離せば解除。
    GIF

ステートリスト

  • ツールバーの「ステートリスト」をクリックすることで開閉。
  • 左側にステートの一覧が表示されるのでステートをクリックすると選択される。
    GIF
  • 検索バーから、名前で検索(一部一致)、挙動の型で検索(全一致)が可能。
    GIF

ParameterContainerについて

ParameterContainerはArborFSM間でのデータの共有などを行う際に使用するコンポーネントです。

GameObjectにParameterContainerを追加し、各種ある型のパラメータを設定します。

ParameterContainerの追加

  • 適用したいGameObjectを選択。
    「メニュー > Component > Arbor > ParameterContainer」を選択 。
  • あるいはInspectorの「Add Componentボタン > Arbor > ParameterContainer」を選択。
    GIF
  • また、HierarchyのCreateボタン「Arbor > ParameterContainer」からParameterContainerがアタッチされた状態のGameObjectが作成できる。
    GIF

パラメータの追加

  • 「Parameters」の右下の+ボタンをクリック。
    追加したい型を選択。
    GIF

パラメータの編集

  • 名前、値を選択し編集。
    GIF

パラメータの削除

  • パラメータを選択し、-ボタンをクリック。
    GIF

GlobalParameterContainerについて

GlobalParameterContainerはシーンを変更しても保持しておきたいパラメータがある場合に使用するコンポーネントです。

GlobalParameterContainerの追加

  • 適用したいGameObjectを選択。
    「メニュー > Component > Arbor > GlobalParameterContainer」を選択 。
  • あるいはInspectorの「Add Componentボタン > Arbor > GlobalParameterContainer」を選択。
    GIF
  • また、HierarchyのCreateボタン「Arbor > GlobalParameterContainer」からGlobalParameterContainerがアタッチされた状態のGameObjectが作成できる。
    GIF

GlobalParameterContainerの設定

  • あらかじめシーン間で共有したいパラメータを設定したParameterContainerを作成し、Prefab化。
  • GlobalParameterContainerが追加されているGameObjectを選択。
    InspectorのPrefabに作成しておいたParameterContainerのPrefabを指定。
    GIF

 コーディング

C#、JavaScript、一応Booのスクリプトを作成して自作の挙動や演算処理を用意できます。

StateBehaviourスクリプトファイルの作成

  • Projectウィンドウから作成したい場所で右クリック。
  • 右クリックメニューから、「Create > Arbor > StateBehaviour」からお好きな言語を選択。
  • ファイル名を入力して決定

ステートの接続

  • 作成したスクリプトにpublicもしくはSerializeField属性をつけたStateLinkを宣言する。
    宣言すれば自動的にArbor Editorで編集可能になる。

    using UnityEngine;
    using Arbor;
    
    public class TestBehaviour : StateBehaviour
    {
    	public StateLink nextState;
    	// 略
    }
    

  • 遷移したいタイミングでTransitionを呼ぶ。

    Transition( nextState );
    

演算ノードからの入力

  • 作成したスクリプトにpublicもしくはSerializeField属性をつけたInputSlotIntやInputSlotFloatなどを宣言する。
    (ジェネリッククラスのInputSlot<T>はUnityの仕様上シリアライズされないため、かならず継承したクラスを使用してください)
    宣言すれば自動的にArbor Editorで編集可能になる。

    using UnityEngine;
    using Arbor;
    
    public class TestBehaviour : StateBehaviour
    {
    	public InputSlotInt slotInt;
    	// 略
    }
    

  • 値を取得するにはGetValueメソッドを使用する。
    int data = 0;
    slotInt.GetValue(ref data);
    if (data == 10)
    {
    	Debug.Log("Test");
    }
    

演算ノードからの入力(Flexible)

  • 作成したスクリプトにpublicもしくはSerializeField属性をつけたFlexibleIntやFlexibleFloatなどを宣言する。
    using UnityEngine;
    using Arbor;
    
    public class TestBehaviour : StateBehaviour
    {
    	public FlexibleInt flexible;
    	// 以下略
    }
    


    ArborEditorウィンドウでCalculucatorを選択すれば演算ノードからの入力を受け付ける。

  • 値を取得するにはvalueプロパティを使用する。
    if (flexible.value == 10)
    {
    	Debug.Log("Test");
    }
    

演算ノードへの出力

  • 作成したスクリプトにpublicもしくはSerializeField属性をつけたOutputSlotIntやOutputSlotFloatなどを宣言する。
    (ジェネリッククラスのOutputSlot<T>はUnityの仕様上シリアライズされないため、かならず継承したクラスを使用してください)
    宣言すれば自動的にArbor Editorで編集可能になる。

    using UnityEngine;
    using Arbor;
    
    public class TestBehaviour : StateBehaviour
    {
    	public OutputSlotInt slotInt;
    	// 以下略
    }
    

  • 値を設定するにはSetValueメソッドを使用する。
    slotInt.SetValue(10);
    

エディタ拡張

  • Unityで使用可能なインスペクタ拡張やPropertyDrawerなどがStateBehaviourにも使用できる

注意点

  • MonoBehaviourのenabledは実行制御のために内部で使用しているため、代替となるbehaviourEnabledを使用してください。

次のステップへ