ひとことで
キャラクターが決まった数の「状態」のどれか 1 つにいて、条件がそろうと別の状態へ移るしくみです。敵なら「巡回」「警戒」「追跡」「攻撃」「捜索」、プレイヤーなら「立ち」「走り」「ジャンプ」「落下」のように、状態ごとにする行動と、次の状態へ移る条件だけを書けばよいので、小さな判断をわかりやすく作れます。ゲームの AI、アニメーション、UI、ゲームの進行など、あらゆる所で使われる最も基本的な設計です。
ゲームでの使いどころ
- 敵の見張り:巡回 → 気づく → 追う → 見失う → 探す → 戻る、というステルスゲームの定番の流れ。
- プレイヤーの操作:地上・空中・はしご・泳ぎで、入力の意味や物理の扱いを切り替える(入力の先行受付と組み合わせる)。
- アニメーションの遷移:Unity の Animator や Unreal の State Machine。待機・歩き・走り・攻撃の間を、条件と遷移時間で結ぶ。
- ゲームの画面や進行:タイトル → ロード → ゲーム中 → ポーズ → リザルト。
しくみ
状態機械は、次の 3 つで決まります。
- 状態の集合:巡回、警戒、追跡、攻撃、捜索。
- 遷移:どの状態から、どの条件で、どの状態へ移るか(矢印)。
- 状態ごとの処理:入ったとき(enter)、いる間毎フレーム(update)、出るとき(exit)にすること。
毎フレーム、今の状態の update を実行し、その状態から出ている矢印の条件を順に調べて、成り立ったものがあれば移ります。移るときは、前の状態の exit と次の状態の enter を呼びます。たとえば「追跡」の enter で走るアニメーションに切り替え、exit で最後に見た位置を記録する、という具合です。
状態の数が なら矢印は最大 本です。状態が少ないうちは図に描いて全体を確かめられるのが強みですが、増えると矢印が爆発的に増えるのが弱点です。
実装のポイント
- 状態の中の時間:「2 秒見えなければ」「警戒して 0.8 秒たったら」のように、状態に入ってからの時間を条件に使うことがよくあります。enter で 0 に戻します。
- 遷移の間を作る:見えた瞬間に追跡を始めるより、「警戒」をはさんで気づくまでの間を作ると、プレイヤーが隠れる余地ができ、遊びやすくなります。
- 階層化:「戦闘」という大きな状態の中に「追跡」「攻撃」「隠れる」の小さな状態機械を入れる(階層型状態機械、HFSM)と、「どの戦闘の状態からでも、体力が 0 なら死亡へ」のような共通の矢印を 1 本で済ませられます。
- データで持つ:状態と遷移を表(データ)で持ち、エディタで編集できるようにすると、プログラマー以外も調整できます。
つまずきやすい点
- 矢印の爆発:状態が 10、20 と増えると、どこからどこへ移れるかが追えなくなります。階層化するか、優先順位で判断を組むビヘイビアツリーを検討します。
- 遷移の順番:同時に複数の条件が成り立つとき、どれを先に調べるかで結果が変わります。優先したい条件を先に書きます。
- 状態をまたぐ情報:「最後に見た位置」のように、複数の状態で使う情報は、状態の外(キャラクターやブラックボード)に置きます。
デモで試すこと
- 見張りは「巡回」から始まります。緑の球(プレイヤー)が視界の扇形に入ると「警戒」に移り、立ち止まってこちらを向きます。右下の図で、今の状態と、直前に通った矢印が光ります。
- 見え続けると「追跡」、近づくと「攻撃」に移ります。攻撃を受けたプレイヤーはスタート地点へ戻されるので、見張りは見失って「捜索」に移り、最後に見た位置で見回してから「巡回」に戻ります。
- 緑の球をドラッグして、壁の陰に隠れてみてください。「追跡」から「捜索」へ移る様子がわかります。
- 「視界の距離」を変えると、気づかれやすさが変わり、遷移の起こり方が変わります。