【Unity】AIで自動行動する敵キャラクターの作り方

敵AIの作り方 ゲーム制作メモ

Unityに限らず、ゲームを作っていると多くの場合で「敵キャラクター」が必要になる場合があります。

一口に敵キャラクターといっても様々だと思いますが、中でも「AIで状況を判断して自動行動する敵キャラクター」は特に需要が高いと思われます。しかし、このような敵キャラは作るのが比較的難しいため、どうやって作ればいいのか分からないという方も多いのではないでしょうか。

そこで今回は3Dゲーム用の敵キャラを例に挙げて、AIを持つ敵キャラの作り方を説明していきますね。

スポンサーリンク

敵キャラクターに必要な機能

では、はじめに「ゲームの敵キャラクター」に必要な機能を整理していきましょう。前提として次のようなゲームに使う敵キャラについて考えるものとします:

  • 3Dゲーム
  • アクション性の高いゲーム

そうすると主に必要な機能としては次の2項目を挙げられます。

  1. 経路探索:(例)障害物に引っかからずにプレイヤーを追いかける
  2. 状況判断:(例)プレイヤーを見つけたら攻撃する

経路探索

まず一つ目は経路探索です。アクション性の高いゲーム(特にアクションゲーム、FPS・TPS等)では、敵キャラクターが適切に動かなければゲームが面白くなりません。そこで障害物を上手く避けて目的地に移動できるようにする必要があります。

経路探索の処理は自力で実装しようとすると難しいジャンルですが、最近のゲームエンジンではその辺を手軽に解決できるAPIが提供されているのでそれを使えばOKでしょう。

状況判断

次に二つ目は状況判断です。アクション性の高いゲームでは敵キャラクターとの戦闘を行う場面がよくあると思いますが、そこで上手く状況を判断して立ち回るAIが求められます。

状況判断を行うAIの種類は色々あり、実際にどれを使えばよいのかはゲームによりけりです。状況判断によく使われるAIは次の通りです。

  • ルールベースAI:設定された条件によって判断
  • ステートベースAI:状況に合った状態(ステート)を実行
  • ビヘイビアベースAI:行動をツリー化し、そのツリーをたどって判断
  • ユーティリティベースAI:行動の見返りを計算して、最も多くの見返りのある行動を実行

Unityでの敵キャラクターの具体的な作り方

では、ここから敵キャラクターの作り方をもう少し具体的に見ていきましょう。Unityで敵キャラクターを実装する方法は次の通りです。

  • 経路探索:NavMeshAgentを使う
  • 状況判断:ステートベースAIを実装する

経路探索→NavMeshAgent

まず経路探索については、Unityに「NavMeshAgent」という経路探索コンポーネントが用意されているのでそれを使いましょう。なかなか癖が強い機能ではありますが、上手く使えば手軽に経路探索を行うことができます。

NavMeshAgentの使い方は姉妹サイトの「ナビメッシュエージェント(NavMeshAgent)の使い方」で詳しく説明しているので、そちらをご覧いただければと思います。

状況判断→ステートベースAI

さて、次は状況判断のAIの作り方です。先述の通りAIの種類は色々ありますが、ここでは汎用性が高く・実装が簡単な「ステートベースAI」の作り方を紹介します。

ステートの作成

まず、列挙型を使って必要なステートを作成します。

public enum EnemyAiState
{
  WAIT,			//行動を一旦停止
  MOVE,			//移動
  ATTACK,		//停止して攻撃
  MOVEANDATTACK,	//移動しながら攻撃
  IDLE,			//待機
  AVOID,		//回避
}

public EnemyAiState aiState = EnemyAiState.WAIT;

AIの準備

次にAIの準備やメインルーチンの処理を行うメソッドを用意します。

protected void SetAi()
{
  if (isAiStateRunning)
  {
    return;
  }

  InitAi();
  AiMainRoutine();

  aiState = nextState;

  StartCoroutine("AiTimer");
}

InitAIメソッドはAIの初期化を行うメソッドで、AiTimerメソッドは思考のインターバルを設定するコルーチンです。

AiTimerが動作している間はisAiStateRunningがTrueになるようにすると、その時は処理が実行されなくなります。このようにしているのは毎フレーム思考ルーチンを走らせる必要がないからです。

AIのメインルーチン

そうしたらAIのメインルーチンをキャラクターごとに書きます。例えば、

  • 普段は適当に移動
  • プレイヤーがshootDistanceよりも近づいたら移動しながら攻撃

という行動をとる敵の場合なら次のようになります。

protected override void AiMainRoutine()
{
  if (wait)
  {
    nextState = EnemyAiState.WAIT;
    wait = false;
    return;
  }

  if (enemyCanShoot && isChasing && distance < Mathf.Pow(shootDistance, 2))
  {
    nextState = EnemyAiState.MOVEANDATTACK;
  }
  else
  {
    nextState = EnemyAiState.MOVE;
  }
}

ここでwaitは思考ルーチンを強制的に停止させるフラグです。停止フラグが立った場合はWAITステートに遷移し、その後の判断は行いません。

行動実行

あとは実際の行動処理をUpdate等から呼び出せばOKです。

protected virtual void UpdateAI()
{
  SetAi();

  switch (aiState)
  {
    case EnemyAiState.WAIT:
      Wait();
      break;
    case EnemyAiState.MOVE:
      Move();
      break;
    case EnemyAiState.ATTACK:
      Attack();
      break;
    case EnemyAiState.MOVEANDATTACK:
      MoveAndAttack();
      break;
    case EnemyAiState.IDLE:
      Idle();
      break;
    case EnemyAiState.AVOID:
      Avoid();
      break;
  }
}

これでステートベースAIを実装することができました。

ちなみに、アセットストアにはビヘイビアベースAIを導入できるアセットがいくつか販売されているので、より高度な状況判断ができるAIを作りたい方はストアを見てください。

おわりに:敵キャラクターを自作してゲームを面白くしよう

以上、簡単ではありますがUnityでの敵キャラクターの作り方を紹介しました。

面白いゲームを作るためには敵キャラクターを上手く作ることは欠かせません。ぜひ今回の内容を足掛かりとして敵キャラの作り方を研究してみてください。