# ステートマシン

# ステートマシンとは？

ステートマシンは、挙動を１つの状態として、条件によって状態を切り替えていく仕組みを言います。

Arborでは、ArborFSMコンポーネントをGameObjectに追加することでステートマシンが使えるようになります。

## 例：スイッチとライト

スイッチと電灯を考えてみます。

- スイッチOFFならライトは消える。
- スイッチONならライトが点く。
- スイッチを条件として、ライトの状態が切り替わります。

ArborFSMで仮組すると以下のようになります。

Destroyメッセージが送られてきた場合に爆発エフェクトを出し削除する挙動も仮組されています。

詳しい解説は後程行います。

# ノードの構成要素

## 開始ステート

ArborFSMが開始した際に一番初めに実行されるステートです。

１つのグラフに必ず１つ必要です。

## ステート

通常のステートです。

開始ステートや他のステートから遷移することで実行されます。

## 常駐ステート

実行中ノードがどれかにかかわらず常に実行されるステートです。

何らかの割り込み判定などをここで行います。

また、常に実行されているため、常駐ステートから他のステートへの遷移は可能ですが、他のステートから常駐ステートへは遷移できません。

## リルートノード

接続ラインの経路を調整するためのノードです。

接続ラインが交差して見にくい場合に使用します。

ラインの方向もこのノードで調整できます。

## StateBehaviourスクリプト

ステートの挙動を処理するためのスクリプトです。

開始ステートや通常ステート、常駐ステートのすべてに設定できます。

１つのステートに複数のStateBehaviourを追加できるため、挙動を組み合わせて状態を作成できます。

StateBehaviourスクリプトの作成についてはこちら。

スクリプティング : StateBehaviour

## 組み込みStateBehaviour

例に出ているActivateGameObjectやOnTriggerEnterTransitionなど、あらかじめ組み込まれている挙動もStateBehaviourスクリプトで記述されています。

組み込みStateBehaviourのリファレンスはこちらを参照してください。

Arborリファレンス : StateBehaviours

## StateLinkについて

状態遷移を行うにはStateLinkを使用します。

StateBehaviourにStateLinkフィールドを宣言すると、Arbor Editorにフィールドが表示されます。

接続することで、実行時にStateBehaviourスクリプトの記述に従って状態遷移が行われます。

### 操作方法

操作 | 方法
--- | ---
接続 | ドラッグ＆ドロップ
切断 | 接続ラインを右クリックし「切断」を選択。

### TransitionTiming

遷移するタイミングは即座に行われるのではなく、TransitionTimingの指定に従います。

TransitionTimingはStateLinkの歯車アイコンをクリックすると開く設定ウィンドウによって行えます。

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

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

# 例の解説

では、先ほどの例をもう一度見てみましょう。

- Light Offステート
  - まず、開始ステートのLight Offステートから始まる。
  - ActivateGameObectにより、Spotlightオブジェクトが非アクティブに変更される。
    Arborリファレンス : ActivateGameObject
  - OnTriggerEnterTransitionにより、Playerタグのオブジェクトが入ったらLight Onステートに遷移する。
    Arborリファレンス : OnTriggerEnterTransition
    (OnTriggerEnterTransitionを使用するには、ArborFSMのあるGameObjectにColliderなどの設定が必要です)
- Light Onステート
  - ActivateGameObectにより、Spotlightオブジェクトがアクティブに変更される。
  - OnTriggerExitTransitionにより、Playerタグのオブジェクトが出たらLight Offステートに遷移する。
    Arborリファレンス : OnTriggerExitTransition
    (OnTriggerExitTransitionを使用するには、ArborFSMのあるGameObjectにColliderなどの設定が必要です)
- Wait Triggerステート
  - 常駐ステートなので、どのステートが実行されているかにかかわらず常時実行される。
  - TriggerTransitionにより、Destroyメッセージが来たらExplosion & Destroyステートに遷移する。
    Arborリファレンス : TriggerTransition
    - なお、Triggerメッセージを送るにはSendTriggerを使用します。
      Arborリファレンス : SendTrigger
      他のFSMからSendTriggerを使用して、間接的に遷移命令を出す形式です。
- Explosion & Destroyステート
  - InstantiateGameObjectにより、プレハブをインスタンス化。
    Arborリファレンス : InstantiateGameObject
    (ここでは仮組のため空のままになっていますが、パーティクルなどを設定する想定です)
  - DestroyGameObjectにより、LightFSMオブジェクト(自分自身のGameObject)を破棄。
    Arborリファレンス : DestroyGameObject

状態に挙動を組み合わせ、遷移条件に合致したら遷移していく流れがわかったかと思います。

今回のような簡単な例であれば直接MonoBehaviourを書いたほうが楽という方もいるかと思いますが、

状態が複数入り乱れるようになった際、グラフ形式で視覚化できるのは大きな利点となるでしょう。

# ステートマシンの使い方

詳しい使い方はこちらを参照してください

ステートマシンの使い方

# スクリプティング

スクリプトによるカスタマイズについてはこちらを参照してください

スクリプティング : StateBehaviour