ゲームAIは、状態ごとに整理すると管理しやすくなります。
ステートマシンパターンが、実装の核心です。
この記事では、設計から実装まで詳しく解説します。
✨ この記事でわかること
- ステートマシンの基本概念
- 状態の定義と遷移
- SRPGでの実装例
- アクションゲームでの実装例
- 実装例とコード

ステートマシンは、AIの行動を明確にします。状態を分けることで、デバッグもしやすくなります。
\あなたにピッタリのシミュレーションゲーム制作講座を見つけよう!/
おすすめ第1位
経営シミュレーション×
農場ゲームの作り方講座
Unity6対応・農場×経営の2ジャンル融合。AIエージェントを独自実装できる唯一の講座。未経験でも完成まで到達できる丁寧な解説が魅力。
本格派・高難易度
UnityシミュレーションRPG
の作り方講座(SRPG)
本格SRPGのAI設計・グリッドシステムを全16回で習得。制作難易度が高いSRPGを作れるスキルは、他と大きく差がつく強みになります。
初心者にもおすすめ
Unity ノンフィールドRPG
+スレスパ風JRPG講座
Slay the Spire風デッキ構築×JRPGをUnityで実装。Unity6・スマホ化対応で、初心者がゲーム開発の第一歩を踏み出すのに最適な講座です。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
ステートマシンの基本概念

ゲーム開発において「賢いAI」とは、状況に合わせて迷いなく行動を選択できるAIを指します。
しかし、AIに複雑な動きをさせようとすればするほど、プログラムはスパゲッティのように絡まり、予期せぬバグを生みがちです。
そこで登場するのが「ステートマシン(有限状態機械)」です。
これは、AIの複雑な頭脳を「現在の状態」というシンプルな箱に分けて整理する設計手法です。
なぜこの手法が最強のAIを作る鍵となるのか、その基本構造を見ていきましょう。
ステートマシンを構成する「最強の3要素」は以下の通りです。
- 状態(State):AIが今まさに何をしているか(例:のんびり待機、必死に追跡、怒りの攻撃)。一度に取れる状態は必ず「1つだけ」に限定するのがポイントです。
- 遷移(Transition):状態を切り替えるための「きっかけ」です。「プレイヤーが視界に入った」「HPが半分になった」といった条件がこれにあたります。
- アクション(Action):それぞれの状態で実行される具体的な処理です。待機中なら「アニメーション再生」、追跡中なら「経路探索」といった具合に、役割を明確に分離します。
なぜステートマシンが「最強」の設計なのか?
ステートマシンが最強と言われる最大の理由は、「AIの振る舞いを100%コントロール下に置けるから」です。
もしステートマシンを使わずに「if文」だけでAIを作ろうとすると、「攻撃しながら歩き、同時に待機アニメーションが流れる」といった矛盾したバグが簡単に発生してしまいます。
しかし、状態を箱で分けるステートマシンなら、一度に一つの行動しか許可しないため、動作が非常に安定します。
また、新しい行動(例:体力が減ったら逃げる)を追加したい時も、既存のコードを壊さずに「新しい箱と矢印」を付け足す感覚で拡張できるのです。
この安定感と拡張性こそが、プロの現場でも長年愛用されている理由です。
では、この強力な仕組みを具体的にどうプログラムに落とし込んでいくのか。

まずは最もシンプルで応用が効く、C#の列挙型(enum)を使った実装方法からマスターしていきましょう。
基本的なステートマシンの実装
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
using UnityEngine; public enum AIState { Idle, // 待機 Chase, // 追跡 Attack, // 攻撃 Return // 戻る } public class SimpleStateMachine : MonoBehaviour { public AIState currentState = AIState.Idle; private Transform target; private Vector3 startPosition; void Start() { startPosition = transform.position; } void Update() { switch (currentState) { case AIState.Idle: UpdateIdle(); break; case AIState.Chase: UpdateChase(); break; case AIState.Attack: UpdateAttack(); break; case AIState.Return: UpdateReturn(); break; } } void UpdateIdle() { // 敵を探す target = FindNearestEnemy(); if (target != null) { float distance = Vector3.Distance(transform.position, target.position); if (distance <= detectionRange) { currentState = AIState.Chase; } } } void UpdateChase() { if (target == null) { currentState = AIState.Idle; return; } float distance = Vector3.Distance(transform.position, target.position); if (distance <= attackRange) { currentState = AIState.Attack; } else if (distance > maxChaseRange) { currentState = AIState.Return; } else { MoveTowardsTarget(); } } void UpdateAttack() { if (target == null) { currentState = AIState.Idle; return; } float distance = Vector3.Distance(transform.position, target.position); if (distance > attackRange) { currentState = AIState.Chase; } else { PerformAttack(); } } void UpdateReturn() { float distance = Vector3.Distance(transform.position, startPosition); if (distance < 0.5f) { currentState = AIState.Idle; } else { MoveTowardsStart(); } } Transform FindNearestEnemy() { // 最も近い敵を探す // 実装は省略 return null; } void MoveTowardsTarget() { // ターゲットに向かって移動 } void MoveTowardsStart() { // 開始位置に戻る } void PerformAttack() { // 攻撃処理 } public float detectionRange = 10f; public float attackRange = 2f; public float maxChaseRange = 15f; } |
このコードで、基本的なステートマシンが実装できます。
状態に応じて、AIの行動が切り替わります。
SRPGでの実装例

SRPGでは、ターン制のステートマシンが有効です。
実装方法を紹介します。
SRPG敵AIのステートマシン
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
public enum SRPGAIState { WaitForTurn, // ターン待機 SelectAction, // 行動選択 Move, // 移動 Attack, // 攻撃 Skill, // スキル使用 EndTurn // ターン終了 } public class SRPGEnemyAI : MonoBehaviour { public SRPGAIState currentState = SRPGAIState.WaitForTurn; private Unit currentUnit; private Unit targetUnit; private ActionCandidate selectedAction; public void ProcessTurn(Unit unit) { currentUnit = unit; currentState = SRPGAIState.SelectAction; while (currentState != SRPGAIState.EndTurn) { UpdateState(); } } void UpdateState() { switch (currentState) { case SRPGAIState.SelectAction: SelectBestAction(); break; case SRPGAIState.Move: ExecuteMove(); break; case SRPGAIState.Attack: ExecuteAttack(); break; case SRPGAIState.Skill: ExecuteSkill(); break; } } void SelectBestAction() { // 最適な行動を選択 targetUnit = FindBestTarget(); if (IsInAttackRange(targetUnit)) { selectedAction = new ActionCandidate { actionType = ActionType.Attack, targetUnit = targetUnit }; currentState = SRPGAIState.Attack; } else { selectedAction = new ActionCandidate { actionType = ActionType.Move, targetPosition = GetMoveTarget(targetUnit) }; currentState = SRPGAIState.Move; } } void ExecuteMove() { // 移動を実行 currentUnit.MoveTo(selectedAction.targetPosition); currentState = SRPGAIState.EndTurn; } void ExecuteAttack() { // 攻撃を実行 BattleSystem.ExecuteAttack(currentUnit, targetUnit); currentState = SRPGAIState.EndTurn; } void ExecuteSkill() { // スキルを実行 currentState = SRPGAIState.EndTurn; } Unit FindBestTarget() { // 最適なターゲットを探す // 実装は省略 return null; } bool IsInAttackRange(Unit target) { int distance = Mathf.Abs(currentUnit.gridX - target.gridX) + Mathf.Abs(currentUnit.gridY - target.gridY); return distance <= currentUnit.stats.attackRange; } Vector2Int GetMoveTarget(Unit target) { // 移動目標位置を計算 // 実装は省略 return Vector2Int.zero; } } |
このコードで、SRPG敵AIのステートマシンが実装できます。
ターン制に合わせて、状態が遷移します。

SRPGのAIは、ターン制に合わせて状態を管理します。行動選択→移動→攻撃の流れを、状態で管理しましょう。
アクションゲームでの実装例

アクションゲームでは、リアルタイムのステートマシンが有効です。
実装方法を紹介します。
アクション敵AIのステートマシン
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
public enum ActionAIState { Patrol, // 巡回 Alert, // 警戒 Chase, // 追跡 Attack, // 攻撃 Stunned, // スタン Dead // 死亡 } public class ActionEnemyAI : MonoBehaviour { public ActionAIState currentState = ActionAIState.Patrol; private Transform player; private Vector3 patrolStart; private Vector3 patrolEnd; private float stateTimer = 0f; void Update() { stateTimer += Time.deltaTime; switch (currentState) { case ActionAIState.Patrol: UpdatePatrol(); break; case ActionAIState.Alert: UpdateAlert(); break; case ActionAIState.Chase: UpdateChase(); break; case ActionAIState.Attack: UpdateAttack(); break; case ActionAIState.Stunned: UpdateStunned(); break; } } void UpdatePatrol() { // 巡回 Patrol(); // プレイヤーを発見 if (DetectPlayer()) { currentState = ActionAIState.Alert; stateTimer = 0f; } } void UpdateAlert() { // 警戒状態 if (stateTimer >= alertDuration) { if (IsPlayerInRange()) { currentState = ActionAIState.Chase; } else { currentState = ActionAIState.Patrol; } stateTimer = 0f; } } void UpdateChase() { // 追跡 ChasePlayer(); float distance = Vector3.Distance(transform.position, player.position); if (distance <= attackRange) { currentState = ActionAIState.Attack; stateTimer = 0f; } else if (distance > maxChaseRange) { currentState = ActionAIState.Patrol; stateTimer = 0f; } } void UpdateAttack() { // 攻撃 if (stateTimer >= attackCooldown) { PerformAttack(); stateTimer = 0f; // 攻撃後は追跡に戻る currentState = ActionAIState.Chase; } } void UpdateStunned() { // スタン状態 if (stateTimer >= stunDuration) { currentState = ActionAIState.Alert; stateTimer = 0f; } } void Patrol() { // 巡回処理 } void ChasePlayer() { // プレイヤーを追跡 } bool DetectPlayer() { // プレイヤーを発見 return false; } bool IsPlayerInRange() { // プレイヤーが範囲内にいるか return false; } void PerformAttack() { // 攻撃処理 } public float alertDuration = 2f; public float attackCooldown = 1f; public float stunDuration = 3f; public float attackRange = 2f; public float maxChaseRange = 10f; } |
このコードで、アクション敵AIのステートマシンが実装できます。
リアルタイムで状態が遷移します。
状態遷移の最適化

状態遷移を最適化することで、AIの動作が滑らかになります。
実装方法を紹介します。
遷移条件の整理
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
[System.Serializable] public class StateTransition { public AIState fromState; public AIState toState; public TransitionCondition condition; } [System.Serializable] public class TransitionCondition { public ConditionType type; public float value; public bool checkTarget; } public enum ConditionType { Distance, // 距離 Health, // HP Timer, // タイマー Flag // フラグ } public class OptimizedStateMachine : MonoBehaviour { public List<StateTransition> transitions = new List<StateTransition>(); public AIState currentState = AIState.Idle; void Update() { // 現在の状態を更新 UpdateCurrentState(); // 遷移をチェック CheckTransitions(); } void UpdateCurrentState() { switch (currentState) { case AIState.Idle: UpdateIdle(); break; // 他の状態も同様 } } void CheckTransitions() { foreach (var transition in transitions) { if (transition.fromState == currentState) { if (CheckCondition(transition.condition)) { ChangeState(transition.toState); break; } } } } bool CheckCondition(TransitionCondition condition) { switch (condition.type) { case ConditionType.Distance: return CheckDistance(condition.value); case ConditionType.Health: return CheckHealth(condition.value); case ConditionType.Timer: return CheckTimer(condition.value); default: return false; } } void ChangeState(AIState newState) { // 状態を変更 OnStateExit(currentState); currentState = newState; OnStateEnter(newState); } void OnStateEnter(AIState state) { // 状態に入った時の処理 } void OnStateExit(AIState state) { // 状態を出た時の処理 } } |
このコードで、状態遷移が最適化されます。
遷移条件をデータ化することで、管理がしやすくなります。
実装例:完全なステートマシンシステム

実際に使える、完全なステートマシンシステムの実装例を紹介します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
using UnityEngine; using System.Collections.Generic; public class CompleteStateMachine : MonoBehaviour { [Header("ステートマシン設定")] public AIState initialState = AIState.Idle; public List<StateTransition> transitions = new List<StateTransition>(); private AIState currentState; private Dictionary<AIState, System.Action> stateUpdateActions; private Dictionary<AIState, System.Action> stateEnterActions; private Dictionary<AIState, System.Action> stateExitActions; void Start() { InitializeStateMachine(); } void InitializeStateMachine() { currentState = initialState; // 状態ごとのアクションを登録 stateUpdateActions = new Dictionary<AIState, System.Action> { { AIState.Idle, UpdateIdle }, { AIState.Chase, UpdateChase }, { AIState.Attack, UpdateAttack } }; stateEnterActions = new Dictionary<AIState, System.Action> { { AIState.Idle, OnIdleEnter }, { AIState.Chase, OnChaseEnter }, { AIState.Attack, OnAttackEnter } }; stateExitActions = new Dictionary<AIState, System.Action> { { AIState.Idle, OnIdleExit }, { AIState.Chase, OnChaseExit }, { AIState.Attack, OnAttackExit } }; OnStateEnter(currentState); } void Update() { // 現在の状態を更新 if (stateUpdateActions.ContainsKey(currentState)) { stateUpdateActions[currentState](); } // 遷移をチェック CheckTransitions(); } void CheckTransitions() { foreach (var transition in transitions) { if (transition.fromState == currentState) { if (CheckCondition(transition.condition)) { ChangeState(transition.toState); break; } } } } void ChangeState(AIState newState) { if (stateExitActions.ContainsKey(currentState)) { stateExitActions[currentState](); } currentState = newState; if (stateEnterActions.ContainsKey(currentState)) { stateEnterActions[currentState](); } } // 各状態の更新処理 void UpdateIdle() { } void UpdateChase() { } void UpdateAttack() { } // 各状態の入退処理 void OnIdleEnter() { } void OnIdleExit() { } void OnChaseEnter() { } void OnChaseExit() { } void OnAttackEnter() { } void OnAttackExit() { } bool CheckCondition(TransitionCondition condition) { // 条件チェック return false; } } |
このコードで、完全なステートマシンシステムが実装できます。
状態の更新、遷移、入退処理を統合しています。
よくある質問(FAQ)

シミュレーションゲームを作りたいなら!Unity入門の森のシミュレーション制作講座で本格ゲーム開発に挑戦しよう
Unity入門の森には、経営・農場・SRPGなど幅広いシミュレーションゲームを作れる講座が揃っています。作りたいジャンルや目標スキルに合わせて選んでみてください。
経営シミュレーション×農場ゲームの作り方講座【Unity6対応!AIエージェント実装まで学べる唯一の講座!】

- 未経験でも完成まで到達できる丁寧な解説
- 農場×経営の2ジャンルを同時に作れる
- 賢く自律行動するAIエージェントを独自実装できる
- 完成後も街づくりゲームに応用可能な高い拡張性
- Unity6対応のモダンな開発手法が身につく
経営シミュレーション×農場ゲームの作り方講座は、シムシティ・牧場物語・どうぶつの森のようなゲームを自分で作れるようになる講座です。
農作物の育成・収穫・販売システムはもちろん、NavMeshを使ったお客さんAIの来店・購入・帰宅の自律行動や、ルールベースAIによる従業員エージェントの実装まで、本格的なゲームAI開発が学べます。
箱庭経営シミュレーションという複合的な題材を通して、Unity中級者・上級者に必要な幅広い開発スキルを一気に習得できる講座です。
Unity6対応・AIエージェント実装まで学べる
農場も経営もコレ1本で完成させよう
→ 経営シミュレーション×農場ゲーム講座を見てみる
応用・拡張性は無限大!自律行動するAIを実装して一歩先のゲーム開発へ!
UnityシミュレーションRPGの作り方講座(SRPG)【全16回!本格タクティクスSRPGをゼロから作れる!】

- ファイアーエムブレム風の本格タクティクスSRPGを0から開発
- 書籍でも情報が少ない戦術シミュレーションを丁寧に解説
- 難解なグリッドシステム・敵AI戦術を完全攻略できる
- 全文コメント入りソースコード付きで初心者でも理解しながら進められる
- Unity入門の森の最高傑作の一つ・解説の丁寧さはトップクラス
UnityシミュレーションRPGの作り方講座(SRPG)は、ファイアーエムブレム・タクティクスオウガ・FFタクティクスのようなターン制ストラテジーシミュレーションゲームを作るための講座です。
移動可能エリアの設定・ターン進行管理・コマンド選択型戦闘・敵AI戦術ストラテジーなど、本格SRPGに必要な機能をすべてゼロから開発します。開発難易度が高いシステムも、全文コメント入りのソースコードと丁寧な解説で確実に理解しながら進められます。
「SRPGを作れる」というスキルは希少価値が高く、Unityエンジニアとして中・上級者を目指す人に強くおすすめの一本です。
本格タクティクスSRPGをゼロから完成させる
難解なグリッドシステムと敵AIを完全攻略しよう
→ UnityシミュレーションRPG(SRPG)講座を見てみる
他では学べない当サイト最高傑作!エンジニアとして頭一つ抜ける希少スキルを今すぐ。
Unity ノンフィールドRPG+スレスパ風JRPG講座【Unity6対応!デッキ構築×JRPGをスマホ向けに作れる!】

- Unity6対応・スマホ化対応で最新環境のゲーム開発が学べる
- Slay the Spire風のデッキ構築システム×JRPGの組み合わせを実装
- 初心者でも取り組みやすい丁寧な解説構成
- ノンフィールドRPGとデッキ構築JRPGの2つを合わせて学ぶのがおすすめ
Unity ノンフィールドRPGの作り方講座+Slay the Spire風デッキ構築JRPGの作り方講座は、今もっともトレンドのデッキ構築型ゲームシステムをJRPGと組み合わせて実装する方法を学べる講座です。
Unity6対応・スマホ化対応の最新カリキュラムで、デッキ構築の核となるシステムをしっかり習得できます。シミュレーション系の設計思想とも親和性が高く、ゲーム開発の幅を広げたい方にもおすすめです。
「Slay the Spireみたいなゲームを自分でも作ってみたい!」という人の最初の一歩として最適な講座です。
Unity6対応・スマホ化対応の最新カリキュラム
トレンドのデッキ構築×JRPGを最速で実装しよう
→ Slay the Spire風デッキ構築JRPG講座を見てみる
SLGの設計思想とも親和性抜群!トレンドシステムを取り入れて開発の幅を広げよう!
まとめ

ステートマシンは、AIの行動を明確にします。
状態を分けることで、デバッグもしやすくなります。
✅ 今日から始める3ステップ
- ステップ1:基本的なステートマシンを実装する(所要2時間)
- ステップ2:状態遷移の条件を実装する(所要2時間)
- ステップ3:状態の入退処理を実装する(所要1時間)
本格的にUnityを学びたい方は、Unity入門の森で実践的なスキルを身につけましょう。
あなたのペースで、少しずつ進めていけば大丈夫です。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。





コメント