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

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

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

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

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

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

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

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

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

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


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

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

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」オブジェクトにアタッチされている

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

  • 処理概要
    敵は攻撃範囲を示す小さなSphereColliderを前面に配置し、同じくOnTriggerStayイベントでプレイヤーが範囲内に入ったかを検知します。
    索敵段階でプレイヤーに近づいた結果、必然的にこの攻撃範囲にプレイヤーが入ってくると判断され、攻撃アクション(例:噛みつき)が開始されます。
  • ポイント
    ・攻撃範囲は「Attack Range Detector」オブジェクトに CollisionDetector をアタッチ
    ・レイヤー設定により、プレイヤーとの当たり判定のみを行うように設定

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

  • 処理概要
    攻撃アニメーション中に、敵は攻撃ヒット判定用の小さなコライダーを有効化します。
    このコライダーは OnTriggerEnter イベントで、初回の衝突時に攻撃ヒットを判定します。
  • ポイント
    ・攻撃ヒット判定用コライダーは、攻撃アニメーション中のみ有効
    ・「Attack Hit Detector」オブジェクトに CollisionDetector をアタッチし、ヒット時に1度だけメソッドが呼び出される

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

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

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

  • 設定例
    ・テリトリー判定はDefaultレイヤーに設定し、プレイヤーとの判定は行わない
    ・攻撃範囲および攻撃ヒット判定はEnemyAttackレイヤーに設定し、Playerとのみ当たり判定が実行されるように制限

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

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

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

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

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

レイヤー設定がDefaultです
ここでは、プレイヤーとの当たり判定はしていません

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

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

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

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

レイヤー設定がEnemyAttackなので、Playerとだけ当たり判定が実行されます

EnemyMoveスクリプト

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

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

MobAttackスクリプト

攻撃範囲にプレイヤーが入った際、攻撃アクションを開始するためのイベントハンドラです。

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

また、攻撃がヒットした際には、以下のように相手の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. 攻撃判定フローチャート

攻撃イベントハンドラ

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

まとめ

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

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


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

Unity

Posted by hidepon