1. はじめに
Unityで2DアクションRPGを作るうえで、敵キャラの動作 は欠かせません。今回の記事では、敵の配置・移動・追跡AI・攻撃処理 を実装していきます!🎮✨
前回(パート3)では、HPバーの作成やカメラの追従設定 を行いました。今回は、プレイヤーが戦う相手となる 敵キャラの動作 を追加して、ゲームらしくしていきます!
この記事で学べること ✅ 敵をフィールドに配置する方法
✅ 敵をランダムに移動させる方法
✅ 敵がプレイヤーを追跡するAIを実装
✅ 敵とプレイヤーの攻撃処理
完成イメージ
- 敵はエリア内をランダムに移動
- プレイヤーが近づくと追跡を開始
- 接触するとプレイヤーにダメージ
- プレイヤーの攻撃が当たると敵がダメージを受ける
これらを実装すると、より アクションRPGらしい戦闘システム になっていきます!💥
それでは、さっそく 敵キャラの配置 から始めていきましょう!🚀
2. 敵の作成
ゲームを面白くするためには、プレイヤーだけでなく敵キャラの動きも重要です。このステップでは、敵キャラの配置、アニメーション設定、基本的な移動処理の準備 を行います。
2.1 敵の基本設定
まずは、敵の基本となるオブジェクトを作成し、アニメーションを設定していきます。
① 敵キャラのオブジェクトを作成
Hierarchy
ウィンドウでCreate Empty
を選択し、新しいオブジェクトを作成します。- 名前を
Enemy
に変更します。 Enemy
を選択し、Inspector
のTag
をEnemy
に設定します。
② 敵のアニメーションを作成
敵キャラのアニメーションは、待機(Idle)と移動(Move) の2種類を用意します。
- Sprite Renderer を追加
Enemy
を選択し、Add Component
からSprite Renderer
を追加。- 立ち絵となるスプライトを
Sprite
に設定。
- Animator を設定
Add Component
からAnimator
を追加。Animation
ウィンドウを開き、新しいアニメーションを作成。Create
→New Clip
から Idle(待機) と Move(移動) のアニメーションを作成。
- アニメーションの登録
Idle
には停止しているときのアニメーションを設定。Move
には動いているときのアニメーションを設定。
2.2 敵の基本コンポーネントを追加
次に、敵キャラが物理演算に対応し、プレイヤーと衝突できるようにします。
BoxCollider2D
を追加Add Component
からBoxCollider2D
を追加し、サイズを調整。- これにより、敵キャラとプレイヤーが当たり判定を持つようになります。
Rigidbody2D
を追加Add Component
からRigidbody2D
を追加。Gravity Scale
を0
に設定(重力の影響を受けないように)。Freeze Rotation (Z)
にチェックを入れる(回転しないように固定)。
2.3 敵のアニメーション制御
敵の Idle
と Move
のアニメーションを切り替えるために、Animator
の設定を行います。
- Animator を開く
Window
→Animation
→Animator
を開く。
- パラメーターを追加
Parameters
タブで+
ボタンをクリックし、Bool
型のパラメーターを作成。- 名前を
Moving
にする。
- アニメーションの遷移を設定
Idle
からMove
へ矢印(遷移)を追加。Move
からIdle
へ矢印(遷移)を追加。
- 遷移の条件を設定
Idle → Move
の矢印を選択し、Conditions
にMoving = true
を追加。Move → Idle
の矢印を選択し、Conditions
にMoving = false
を追加。
- 遷移のスムーズ化
Idle → Move
のTransition Duration
を0
に設定。Move → Idle
のExit Time
を0
にし、Transition Duration
を0
に設定。

2.4 動作確認
ここまでの設定が正しく反映されているか確認しましょう。
- ゲームを再生
Enemy
が正しく表示されるか確認。Animator
を開き、Moving
の値を手動で変更してIdle
とMove
が正しく切り替わるかチェック。

このステップでは、敵キャラの配置と基本的なアニメーションの設定 を行いました。次のステップでは、敵がエリア内を徘徊するようにし、プレイヤーを追跡する動きを追加していきます!🔥
3. 敵の移動範囲を設定
敵キャラが無制限に移動してしまうと、マップの外に出たり、予期しない場所へ移動してしまうことがあります。そこで、敵が移動できる範囲を限定する「移動エリア」を作成 し、その範囲内で自由に動くように設定します。
3.1 敵の移動エリアを作成
まず、敵が移動できる範囲(エリア) を決めるために、BoxCollider2D を利用して移動可能エリアを定義 します。
① エリア用の空オブジェクトを作成
Hierarchy
ウィンドウを開く。- 右クリック → Create Empty を選択し、新しい空オブジェクトを作成。
- 名前を「Area」に変更 する。
Inspector
でTransform
のPosition
を(0, 0, 0)
にリセット。
② BoxCollider2D を追加
Area
を選択した状態で、Inspector
のAdd Component
ボタンをクリック。BoxCollider2D
を追加。Size
を変更し、敵が動き回る範囲を適切なサイズに調整。- エリアが狭すぎると敵が動けなくなるため、少し余裕を持たせるのがポイント!
Is Trigger
のチェックは外したまま にする。

3.2 敵をエリア内でランダム移動させる
敵が移動エリアから出ないように、移動範囲を BoxCollider2D の中に限定 します。
これを実現するために、EnemyController
スクリプトに移動処理を追加します。
① スクリプトを作成
Project
ウィンドウでCreate
→C# Script
を選択。- 名前を
EnemyController
に変更。 - 作成したスクリプトを
Enemy
にドラッグ&ドロップしてアタッチ。
② スクリプトのコード
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class EnemyControler : MonoBehaviour
{
private Rigidbody2D rb;
private Animator enemyAnim;
[SerializeField]
private float moveSpeed, waitTime, walkTime;
private float waitCountor, moveCounter;
private Vector2 moveDir;
[SerializeField]
private BoxCollider2D area;
void Start()
{
rb = GetComponent<Rigidbody2D>();
enemyAnim = GetComponent<Animator>();
waitCountor = waitTime;
}
void Update()
{
if (waitCountor > 0)
{
waitCountor -= Time.deltaTime;
rb.velocity = Vector2.zero;
if (waitCountor <= 0)
{
moveCounter = walkTime;
enemyAnim.SetBool("Moving", true);
moveDir = new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f));
moveDir.Normalize();
}
}
else
{
moveCounter -= Time.deltaTime;
rb.velocity = moveDir* moveSpeed;
if (moveCounter <= 0)
{
enemyAnim.SetBool("Moving", false);
waitCountor = waitTime;
}
}
//エリア内しか動けないようにする
transform.position = new Vector3(Mathf.Clamp(transform.position.x, area.bounds.min.x + 1, area.bounds.max.x-1),
Mathf.Clamp(transform.position.y, area.bounds.min.y + 1, area.bounds.max.y - 1),transform.position.z);
}
}
3.3 各パラメータの設定
スクリプトを適用したら、敵の移動設定をカスタマイズ します。
① EnemyController
の Inspector
でパラメータを調整
項目 | 説明 | 例 |
---|---|---|
Move Speed | 移動速度 | 3 |
Wait Time | 待機時間(動かない時間) | 2 |
Walk Time | 移動時間(動く時間) | 2 |
Area | 移動範囲の BoxCollider2D | Area を設定 |
② Area
を EnemyController
に紐づけ
Enemy
のInspector
でEnemyController
のArea
フィールドを探す。Hierarchy
からArea
をEnemyController
のArea
にドラッグ&ドロップ。
3.4 動作確認
- ゲームを再生 し、敵がランダムに動くことを確認。
- 敵がエリア外に出ないかチェック!
- もし敵が外に出てしまう場合は、
BoxCollider2D
のサイズを見直す。
- もし敵が外に出てしまう場合は、
3.5 エリアのサイズを動的に変更する方法(応用編)
もしエリアの大きさをスクリプトで動的に設定したい場合、Start()
で BoxCollider2D
のサイズを取得して制限できます。
void Start()
{
rb = GetComponent<Rigidbody2D>();
enemyAnim = GetComponent<Animator>();
waitCounter = waitTime;
// エリアのサイズを自動取得
if (area != null)
{
float minX = area.bounds.min.x + 1;
float maxX = area.bounds.max.x - 1;
float minY = area.bounds.min.y + 1;
float maxY = area.bounds.max.y - 1;
transform.position = new Vector3(Random.Range(minX, maxX), Random.Range(minY, maxY), transform.position.z);
}
}
この処理を追加すると、敵が必ずエリア内のランダムな位置にスポーン するようになります!
3.6 まとめ
- 「Area」オブジェクトを作成し、BoxCollider2D で移動エリアを定義。
- 敵がエリア内をランダムに移動するようにスクリプトを作成。
- Clamp() を使って、敵がエリア外へ出ないように制限。
- Inspector から移動速度や待機時間をカスタマイズ可能に!

これで、敵がエリアの外に出ることなく、適切な範囲内で動き回るAIが完成 しました!
次のステップでは、敵がプレイヤーを追跡するAI を実装していきます!🔥
4. 敵がプレイヤーを追跡する
敵キャラがエリア内を移動するだけでは物足りませんよね?
そこで、今回は 敵がプレイヤーを追跡するAI を実装します!
プレイヤーが一定範囲に入ると、敵が追いかけてきて、距離が離れると再び徘徊を開始するようにします。
4.1 プレイヤーのタグを設定
敵がプレイヤーを認識できるように、プレイヤーに “Player” タグ を設定しておきます。
Hierarchy
でPlayer
を選択Inspector
のTag
をPlayer
に変更(もし “Player” がなければAdd Tag
から追加)
4.2 敵の追跡処理を追加
EnemyController
に以下の変数を追加します。
[SerializeField]
private bool chase; // 追跡モードのON/OFF
private bool isChasing; // 追跡中かどうか
[SerializeField]
private float chaseSpeed, rangeToChase; // 追跡速度と追跡範囲
private Transform target; // 追跡するプレイヤーの位置
[SerializeField]
private float waitAfterHitting; // 攻撃後の待機時間
[SerializeField]
private int attackDamage; // 敵の攻撃力
Start()
メソッドでプレイヤーを探してターゲットとして設定します。
void Start()
{
target = GameObject.FindGameObjectWithTag("Player").transform;
}
4.3 追跡ロジックの実装
敵は プレイヤーとの距離をチェックし、範囲内なら追跡を開始 します。
- 敵が通常のランダム移動をしている状態
isChasing = false
のときは、ランダムな方向に移動するrangeToChase
の範囲内にプレイヤーを検知するとisChasing = true
に変更し、追跡開始
void Update()
{
if (!isChasing)
{
if (waitCountor > 0)
{
waitCountor -= Time.deltaTime;
rb.velocity = Vector2.zero;
if (waitCountor <= 0)
{
moveCounter = walkTime;
enemyAnim.SetBool("Moving", true);
moveDir = new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f));
moveDir.Normalize();
}
}
else
{
moveCounter -= Time.deltaTime;
rb.velocity = moveDir * moveSpeed;
if (moveCounter <= 0)
{
enemyAnim.SetBool("Moving", false);
waitCountor = waitTime;
}
}
// プレイヤーが追跡範囲内に入ったら追跡開始
if (chase)
{
if (Vector3.Distance(transform.position, target.position) < rangeToChase)
{
isChasing = true;
}
}
}
- プレイヤーを追跡している状態
isChasing = true
の場合、プレイヤーの方向を向いて移動rangeToChase
以上にプレイヤーが離れたら、追跡をやめて通常の移動に戻る
else
{
if (waitCountor > 0)
{
waitCountor -= Time.deltaTime;
rb.velocity = Vector2.zero;
if (waitCountor <= 0)
{
enemyAnim.SetBool("Moving", true);
}
}
else
{
moveDir = target.position - transform.position;
moveDir.Normalize();
rb.velocity = moveDir * chaseSpeed;
}
// プレイヤーが追跡範囲外に出たら追跡をやめる
if (Vector3.Distance(transform.position, target.position) > rangeToChase)
{
isChasing = false;
waitCountor = waitTime;
enemyAnim.SetBool("Moving", false);
}
}
4.4 敵がエリア内でのみ移動するように制限
このままだと、敵がマップの外まで行ってしまうことがあります。
そこで、敵の transform.position
を エリアの範囲内に制限 しましょう。
// エリア外に出ないように制限
transform.position = new Vector3(
Mathf.Clamp(transform.position.x, area.bounds.min.x + 1, area.bounds.max.x - 1),
Mathf.Clamp(transform.position.y, area.bounds.min.y + 1, area.bounds.max.y - 1),
transform.position.z
);
4.5 インスペクターでの設定
スクリプトを Enemy
にアタッチしたら、Inspector
でパラメータを設定しましょう。
項目 | 設定値(例) |
---|---|
Chase | ✅(チェックを入れると追跡ON) |
Chase Speed | 2.0 |
Range To Chase | 5.0 |
Wait After Hitting | 1.0 |
Attack Damage | 10 |
4.6 動作確認
- プレイヤーが近づくと敵が追いかけてくる
- 距離が離れると敵が追跡をやめてランダム移動に戻る
- エリアの外には出ない

これで、敵がプレイヤーを追跡するようになりました!
次は、敵がプレイヤーに攻撃できるようにする 仕組みを作っていきます!💥🔥
5. 敵とプレイヤーの攻撃システム
この記事では、敵とプレイヤーの戦闘システムを実装 します!
- 敵にぶつかるとダメージを受けてノックバック
- プレイヤーの剣で敵を攻撃
- 敵のHPがゼロになると消滅
この流れをスクリプトで作成していきましょう。
5.1 プレイヤーがダメージを受ける&ノックバック処理
敵にぶつかったときに、プレイヤーがダメージを受けてノックバックするようにします。
① PlayerController にノックバック処理を追加
PlayerController
スクリプトを開き、以下のコードを追加します。
private bool isKnockingBack;
private Vector2 knockDir;
[SerializeField]
private float knockbackTime, knockbackForce;
private float knockbackCounter;
[SerializeField]
private float invincibilityTime;
private float invincibilityCounter;
void Update()
{
// 無敵時間をカウントダウン
if (invincibilityCounter > 0)
{
invincibilityCounter -= Time.deltaTime;
}
// ノックバック中の処理
if (isKnockingBack)
{
knockbackCounter -= Time.deltaTime;
rb.velocity = knockDir * knockbackForce;
if (knockbackCounter <= 0)
{
isKnockingBack = false;
}
else
{
return;
}
}
}
// ノックバックの処理
public void KnockBack(Vector3 position)
{
knockbackCounter = knockbackTime;
isKnockingBack = true;
knockDir = transform.position - position;
knockDir.Normalize();
}
// ダメージを受ける処理
public void DamagePlayer(int damage)
{
if (invincibilityCounter <= 0)
{
CurrentHealth = Mathf.Clamp(CurrentHealth - damage, 0, MaxHealth);
invincibilityCounter = invincibilityTime;
if (CurrentHealth == 0)
{
gameObject.SetActive(false);
}
}
// HPバーを更新
GameManager.instance.UpdateHealthUI();
}
② エディタでパラメータを設定
knockbackTime
→0.2
knockbackForce
→30
invincibilityTime
→0.5
5.2 敵がプレイヤーにダメージを与える
次に、敵がプレイヤーにぶつかったときにダメージを与える処理 を追加します。
① EnemyController にダメージ処理を追加
EnemyController
スクリプトを開き、以下のコードを追加します。
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
if (isChasing)
{
PlayerController player = collision.gameObject.GetComponent<PlayerController>();
// プレイヤーにノックバック&ダメージを与える
player.KnockBack(transform.position);
player.DamagePlayer(attackDamage);
waitCountor = waitAfterHitting;
enemyAnim.SetBool("Moving", false);
}
}
}
これで、敵がプレイヤーに当たると ノックバックしてHPが減る 仕様になりました!
5.3 プレイヤーの攻撃処理
次に、プレイヤーの剣で 敵を攻撃できるようにする 仕組みを作ります。
① 剣にコライダーを追加
Sword
にPolygonCollider2D
を追加。IsTrigger
にチェックを入れる。- コライダーのサイズを剣の大きさに調整。
② 敵のタグを作成
Inspector
のTag
でAdd Tag
をクリック。Enemy
タグを作成し、Enemy
オブジェクトに設定。
5.4 剣のスクリプトを作成
- 新しい C# スクリプト
Weapon.cs
を作成 し、以下のコードを記述します。
using UnityEngine;
public class Weapon : MonoBehaviour
{
[SerializeField]
private int attackDamage;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Enemy")
{
collision.gameObject.GetComponent<EnemyController>().TakeDamage(attackDamage, transform.position);
}
}
}
Weapon
スクリプトをSword
にアタッチ。
5.5 敵のダメージ処理
敵がプレイヤーの攻撃を受けると、ダメージを受けてノックバックするようにします。
① EnemyController にダメージ処理を追加
EnemyController
スクリプトに以下のコードを追加します。
[SerializeField]
private int currentHealth;
private bool isKnockingBack;
[SerializeField]
private float knockBackTime, knockBackForce;
private float knockBackCounter;
private Vector2 knockDir;
void Update()
{
if (isKnockingBack)
{
if (knockBackCounter > 0)
{
knockBackCounter -= Time.deltaTime;
rb.velocity = knockDir * knockBackForce;
}
else
{
rb.velocity = Vector2.zero;
isKnockingBack = false;
}
return;
}
}
// ノックバック処理
public void KnockBack(Vector3 position)
{
isKnockingBack = true;
knockBackCounter = knockBackTime;
knockDir = transform.position - position;
knockDir.Normalize();
enemyAnim.SetBool("Moving", false);
}
// ダメージを受ける処理
public void TakeDamage(int damage, Vector3 position)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Destroy(gameObject);
}
KnockBack(position);
}
5.6 エディタでパラメータを設定
PlayerController
のattackDamage
を設定。EnemyController
のcurrentHealth
,knockBackTime
,knockBackForce
を設定。
5.7 動作確認
✅ 敵に剣が当たるとダメージを受ける!
✅ 敵が倒れると消滅!
✅ 敵にぶつかるとプレイヤーがダメージ&ノックバック!
これで、プレイヤーと敵の基本的な攻撃&ダメージ処理が完成しました!🎮✨
6. まとめ
この記事では、敵キャラの配置、移動AI、プレイヤーとの戦闘システム を実装しました。
これにより、プレイヤーが探索中に敵と遭遇し、戦闘できるようになりました!🎮✨
① 敵の配置と移動
Enemy
オブジェクトを作成し、プレイヤーと同様にアニメーション(Idle / Move) を設定。- BoxCollider2D や Rigidbody2D を追加し、敵がゲーム内で動けるようにしました。
EnemyController
スクリプトを作成し、ランダムに徘徊 するように実装。
② プレイヤーを追跡する敵AI
- エリア内のみ移動 するように制御しつつ、プレイヤーが近づいたら追跡 する処理を追加。
Vector3.Distance()
を使用し、プレイヤーとの距離がrangeToChase
より短くなると追跡を開始。- 距離が離れると再びエリア内を徘徊 するように設定しました。
③ 敵とプレイヤーの戦闘
- 敵がプレイヤーに衝突するとダメージを与え、ノックバック する処理を追加。
- プレイヤーの攻撃(剣)を
PolygonCollider2D
で判定し、敵にダメージを与えられるようにしました。 - 敵がダメージを受けるとノックバックし、HPが0になると消滅 するように実装。
④ 戦闘システムをさらに強化するなら?
手動でのAI作成も楽しいですが、もっと高度な戦闘システムを実装したい場合は、
「TopDown Engine」 のようなアセットを活用するのもおすすめです!
このアセットを使うと、移動、攻撃、スキル、敵AI などのシステムを一括で管理でき、よりスムーズに開発できます。