RPGキャラクターの当たり判定処理

2026年10月20日

広告

本資料では、以下の一連の処理について説明します。

  • 敵のテリトリーにプレイヤーが侵入した場合、敵が追尾を開始する
  • プレイヤーが敵の前面に到達した場合、攻撃アクションを開始する
  • 攻撃がヒットした場合、プレイヤーにダメージを与える

1. 敵から見たプレイヤーとの関係性

敵キャラクターは、プレイヤーとの距離や位置に応じて以下の状態を切り替えます。

  • 索敵中
    自身のテリトリーにプレイヤーが侵入しているかを検出し、近づく動作を開始する
  • 攻撃開始
    プレイヤーが敵の前面(攻撃エリア)に入った場合、攻撃アクション(例:噛みつき)を開始する
  • 攻撃ヒット
    攻撃アニメーション中に、プレイヤーとの衝突が確認されれば、ダメージ処理を実行する

2. 3種類のコライダーによる状態別の処理

各状態に応じて、以下のコライダーを使用して当たり判定を行います。

  • テリトリー判定用コライダー
    敵の索敵エリアとして、大きなSphereColliderを用い、OnTriggerStayイベントでプレイヤーの侵入を検知
  • 攻撃範囲判定用コライダー
    敵の前面に小さなコライダー(この記事ではBoxCollider)を設置し、同じくOnTriggerStayでプレイヤーが前に来たかを判定
    ※このコライダーは、索敵段階の結果としてプレイヤーが近づいていることが前提
  • 攻撃ヒット判定用コライダー
    攻撃中にのみ有効化される小さなコライダーで、OnTriggerEnterイベントを用いて攻撃がヒットしたタイミングを捉えます

各コライダーは、個別のゲームオブジェクトにアタッチして管理することで、異なるイベント処理を実現しています。
※1つのオブジェクトに複数のコライダーをアタッチすることも可能ですが、個別にイベントを切り分けるのは難しくなります。

動作の前提条件(設定チェックリスト)

  • Collider:3種類とも Is Trigger にチェックを入れる
  • Rigidbody:トリガーイベントが発生するには、接触する2つのオブジェクトのうち少なくとも一方に Rigidbody(または CharacterController)が付いている
  • Layer Collision Matrix:イベントを受け取りたい組み合わせ(例:DefaultとPlayer)にチェックが入っている(チェックを外すと、Is Triggerでもイベントは発生しません)
  • 作成の順番:CollisionDetector は [RequireComponent(typeof(Collider))] を指定しているため、先にBoxColliderなどのColliderを追加してから、スクリプトを追加する
  • UnityEventの登録:関数は Dynamic Collider の区画から選ぶ(Static Parameters の区画からは選ばない)。詳しくは4.1の折りたたみで解説しています
  • Layer Overrides:Unity 6 のコライダーにある Include Layers / Exclude Layers は Nothing(初期値)のままにする(設定すると、Matrixとは別に衝突する相手が変わり、イベントが来なくなることがあります)

3. 共通で使用する当たり判定用スクリプト

以下は、共通の当たり判定処理を行うための CollisionDetector コンポーネントです。
各コライダーにこのスクリプトをアタッチすることで、OnTriggerStay や OnTriggerEnter イベントをドラッグ&ドロップで設定可能になります。

using System;
using UnityEngine;
using UnityEngine.Events;

// このコンポーネントはColliderに対応しており、トリガーイベントを検出します。
[RequireComponent(typeof(Collider))]
public class CollisionDetector : MonoBehaviour
{
    // トリガー内に他のオブジェクトが滞在している間に発生するイベント
    [SerializeField]
    TriggerEvent onTriggerStay = new TriggerEvent();

    // トリガー内に他のオブジェクトが入ったときに発生するイベント
    [SerializeField]
    TriggerEvent onTriggerEnter = new TriggerEvent();

    // トリガー内での滞在時のイベントハンドラ
    void OnTriggerStay(Collider other)
    {
        onTriggerStay.Invoke(other);
    }

    // トリガーに入った瞬間のイベントハンドラ
    void OnTriggerEnter(Collider other)
    {
        onTriggerEnter.Invoke(other);
    }

    // Collider型のパラメータを持つカスタムUnityEventクラス
    [Serializable]
    public class TriggerEvent : UnityEvent<Collider>
    {
    }
}

4. 各ステージの処理詳細

4.1 索敵中:プレイヤー発見の判定

  • 処理概要
    敵は大きなSphereColliderを用いて自分のテリトリーを設定し、OnTriggerStayイベントでプレイヤーが侵入しているかどうかを常に監視します。
    プレイヤーが侵入している間、敵は追尾アクションを実行します。
  • ポイント
    ・Stayイベントを利用するため、テリトリー内にいる間ずっと処理が実行される
    ・CollisionDetectorが「Collision Detector」オブジェクトにアタッチされている
関数が動かないときは? UnityEventの「Dynamic」の選び方

UnityEventに関数を登録するとき、関数の選択メニューには2つの区画が出ます。

Dynamic Collider(上の区画):OnTriggerStay で受け取った Collider を、そのまま関数に渡します。EnemyMove の OnDetectObject のように、Collider を引数に取る関数は、必ずここから選びます。

Static Parameters(下の区画):インスペクターで決めた固定値を渡す登録方法です。同じ名前の関数が並んでいますが、ここから選ぶと Collider が渡らず、タグの判定などが動きません。

見分け方は、登録したあとの表示です。Dynamicで登録すると、関数名の下に引数の入力欄は出ません。

画面は Unity 6.3 LTS のものです。

4.2 攻撃開始:プレイヤーが前面にいるかの判定

  • 処理概要
    敵は攻撃範囲を示す小さなコライダーを前面に配置し(この記事の画像ではBoxColliderを使用。SphereColliderなど他の形状でも同じように使えます)、同じくOnTriggerStayイベントでプレイヤーが範囲内に入ったかを検知します。
    索敵段階でプレイヤーに近づいた結果、必然的にこの攻撃範囲にプレイヤーが入ってくると判断され、攻撃アクション(例:噛みつき)が開始されます。
  • ポイント
    ・攻撃範囲は「Attack Range Detector」オブジェクトに CollisionDetector をアタッチ
    ・レイヤー設定により、プレイヤーとの当たり判定のみを行うように設定
    ・OnTriggerStayなので、範囲内にいる間は繰り返し呼ばれます。攻撃可能な状態のときだけ攻撃を始める作り(MobStatusの状態管理)にして、攻撃中の再開始を防ぎます

4.3 攻撃ヒット:攻撃が当たったかの判定

  • 処理概要
    攻撃アニメーション中に、敵は攻撃ヒット判定用の小さなコライダーを有効化します。
    このコライダーは OnTriggerEnter イベントで、初回の衝突時に攻撃ヒットを判定します。
  • ポイント
    ・攻撃ヒット判定用コライダーは、攻撃アニメーション中のみ有効
    ・「Attack Hit Detector」オブジェクトに CollisionDetector をアタッチし、攻撃アニメーションでコライダーが有効になったあと、最初に接触したタイミングでメソッドが呼び出される
    ・同じ攻撃で1回だけダメージを与えたい場合は、「ヒット済み」を記録するなどの制御を別途加えると確実です(本資料では基本の仕組みに絞って解説しています)

5. Unityエディタ上のオブジェクト・コンポーネント関係

  • オブジェクト配置例
    ・敵キャラクターに対して、索敵エリア、攻撃範囲、攻撃ヒット用の各Colliderを別々の子オブジェクトとしてアタッチします。
    ・各オブジェクトには CollisionDetector コンポーネントが付与され、インスペクター上でドラッグ&ドロップによりイベント処理が設定されます。
  • 動作確認
    シーンビューでは、ワイヤーフレーム表示で各Colliderの有効/無効がアニメーションと連動していることが確認できます。

6. レイヤー設定による当たり判定の制限

  • 設定例
    ・テリトリー判定はDefaultレイヤーに設定します。DefaultとPlayerの組み合わせはMatrixのチェックを入れたままにして、プレイヤーの侵入を検知します(Is Triggerなので、プレイヤーを押し返すような物理的な衝突は起きません)
    ・攻撃範囲および攻撃ヒット判定はEnemyAttackレイヤーに設定し、Playerとのみ当たり判定が実行されるように制限(敵自身や地面などには反応しません)
    ・Matrixのチェックを外した組み合わせでは、Is Triggerでも OnTriggerStay / OnTriggerEnter は発生しません
判定が反応しないときの調べ方(Physics Debugger)

OnTriggerStay や OnTriggerEnter が呼ばれないときは、Unity の Physics Debugger で当たり判定の状態を目で確認できます。Window → Analysis → Physics Debugger の順に開きます。

Physics Debugger を開いた状態で、シーンビューの Collision Geometry をオンにすると、コライダーの形と範囲が色つきで表示されます。索敵用の球(SphereCollider)が、敵の周りにイメージ通りの大きさで広がっているかを確認できます。

Rigidbody が付いていない物体を選ぶと、Info には「Rigidbody か Articulation Body を持つ GameObject を選んでください」と表示されます。

反応しないときは、次の順番で確認します。

  1. コライダーの範囲が、想定した位置と大きさにあるか(Collision Geometry)
  2. Is Trigger にチェックが入っているか
  3. 接触する2つのオブジェクトのうち、少なくとも一方に Rigidbody が付いているか(Physics Debugger の Info で確認)
  4. 2つのレイヤーの組み合わせが、Layer Collision Matrix でオンになっているか
  5. Layer Overrides の Include Layers / Exclude Layers が Nothing(初期値)になっているか

画面は Unity 6.3 LTS のものです。


7. その他のスクリプト例

敵からみてプレイヤーがテリトリーに入って来れば追いかける

自分のテリトリーに入ってくる時に特定の処理を実行したい

敵の周りに大きなコライダーをアタッチして、ここの中にプレイヤーが入ってきたらイベントを発生させます
OnTriggerStayを使いますが、トリガーイベントが発生する処理をドラッグ&ドロップで選択できるような共通のスクリプトを使っています

レイヤー毎による特定のオブジェクトとの当たり判定設定

レイヤー設定がDefaultです
DefaultとPlayerの組み合わせはMatrixでチェックが入っているため、プレイヤーの侵入を検知できます(Is Triggerなので、プレイヤーを押し返すことはありません)

敵からみてプレイヤーが攻撃範囲にに入って来れば攻撃する

自分の攻撃範囲に入ってくる時に特定の処理を実行したい

敵の前面に小さなコライダーをアタッチして、ここの中にプレイヤーが入ってきたらイベントを発生させます
OnTriggerStayを使いますが、トリガーイベントが発生する処理をドラッグ&ドロップで選択できるような共通のスクリプトを使っています

レイヤー毎による特定のオブジェクトとの当たり判定設定

レイヤー設定がEnemyAttackなので、Playerとだけ当たり判定が実行されます(敵自身や地面などには反応しません)

EnemyMoveスクリプト

プレイヤーとの当たり判定において、Colliderのタグを利用して処理を分岐します。

public void OnDetectObject(Collider collider)
{
    if (collider.CompareTag("Player"))
    {
        // プレイヤーを検知した場合の処理(例:追尾開始)
    }
}

MobAttackスクリプト

攻撃範囲にプレイヤーが入った際、攻撃アクションを開始するためのイベントハンドラです。
OnTriggerStayから呼ばれるため、名前は「Enter」でも、プレイヤーが範囲内にいる間は繰り返し呼ばれます。AttackIfPossible() は「可能なら攻撃する」という名前のとおり、攻撃可能な状態のときだけ攻撃を始める作りにしておきます。

public void OnAttackRangeEnter(Collider collider)
{
    AttackIfPossible();
}

また、攻撃がヒットした際には、以下のように相手のMobStatusスクリプトを取得し、ダメージ処理を実行します。
MobStatusが付いているオブジェクトにColliderも付いている構成なら、GetComponent で取得できます。Colliderが子オブジェクトにあり、MobStatusが親にある構成では、GetComponentInParent<MobStatus>() を使います。

public void OnHitAttack(Collider collider)
{
    var targetMob = collider.GetComponent<MobStatus>();
    if (targetMob == null) return;

    // プレイヤーにダメージを与える
    targetMob.Damage(1);
}

ダメージ処理と死亡処理

ダメージを与えるメソッドは、以下のような流れで実装されます。

  • 状態が「死んでいる」場合は何も行わない
  • ライフを減らす
  • ライフが0より大きい場合は処理終了
  • ライフが0以下の場合、状態を「死んでいる」に変更し、死亡アニメーションとその他の死亡時処理を実行
public void Damage(int damage)
{
    if (_state == StateEnum.Die) return;

    _life -= damage;
    if (_life > 0) return;

    _state = StateEnum.Die;
    _animator.SetTrigger("Die");

    OnDie();
}

protected virtual void OnDie()
{
    // 死亡時の追加処理(現時点では空)
}

8. 攻撃判定フローチャート

攻撃イベントハンドラ

攻撃アニメーションの動き

まとめ

本資料では、敵キャラクターがプレイヤーを検知し、追尾・攻撃・ダメージ処理を行うための当たり判定の仕組みについて解説しました。
各ステージで異なるコライダーとイベント(OnTriggerStay、OnTriggerEnter)を用いることで、柔軟な判定処理を実現しています。
また、レイヤー設定によって特定のオブジェクト間のみで当たり判定を実行するように制御する点も重要です。

これらの手法を応用することで、より複雑で動的なRPGのバトルシステムを構築することが可能になります。


このような設計・実装方法を参考に、実際のプロジェクトでの当たり判定処理の実装を検討してください。

関連記事: 状態管理・攻撃・移動・当たり判定の全体像は、Unityゲームにおける状態管理とキャラクター制御スクリプトの解説(敵の攻撃からプレイヤーの攻撃まで)で解説しています。

訪問数 292 回, 今日の訪問数 1回

広告

Unity

Posted by hidepon