1つのGameObjectに2つのColliderをアタッチする設計に関する技術資料

1. 概要

本資料では、1つのGameObjectに複数のColliderをアタッチする構成 のメリット、実装方法、考慮点について解説します。
この構成は、異なる形状や当たり判定を1つのオブジェクトに持たせる必要がある場合に有効 です。


2. 基本構造と考え方

(1) なぜ1つのGameObjectに複数のColliderを持たせるのか?

  1. 複雑な当たり判定を作成できる
    • 異なる形状(BoxCollider + SphereCollider など)を組み合わせることで、複雑なオブジェクト形状に対応
    • 例: キャラクターの体にCapsuleCollider、手にSphereCollider
  2. 部分ごとの衝突処理を区別できる
    • 1つの Rigidbody に対して、どのColliderが衝突したかを判別可能
    • collision.contacts[].thisCollider.name を使用して判別
  3. トリガーエリアと通常の衝突判定を同時に実装できる
    • 例: 通常のBoxCollider(isTrigger=false)に加え、検出用のSphereCollider(isTrigger=true)を持たせる

3. 利点

(1) 物理計算を統一できる

  • 1つの Rigidbody でオブジェクトの物理挙動を管理できる
  • 各Colliderが個別にRigidbodyを持つと、不安定な物理挙動が発生する可能性がある

(2) 部位ごとの衝突判定が可能

  • collision.contacts[].thisCollider.name を利用して、どのColliderが衝突したか判別できる

(3) トリガーと通常の衝突を分離

  • トリガー(isTrigger=true を活用し、範囲検出と通常の衝突を分けて管理 できる

4. シーン構成例

Robot (GameObject) → Rigidbody
  ├─ BoxCollider (体) → `isTrigger = false`
  ├─ SphereCollider (センサー) → `isTrigger = true`
  • BoxCollider → 物理衝突のため(壁や敵との衝突を検知)
  • SphereCollider → トリガーエリア(プレイヤーが近づいたことを検知)

5. コードサンプル

(1) 1つのオブジェクトに複数のColliderを設定

以下のスクリプトを Robot にアタッチし、2つのColliderの衝突を個別に検出します。

using UnityEngine;

public class MultiColliderObject : MonoBehaviour
{
    private Rigidbody rb;
    private Collider[] colliders;

    void Start()
    {
        // Rigidbodyの取得
        rb = GetComponent<Rigidbody>();

        // すべてのColliderを取得
        colliders = GetComponents<Collider>();

        // 各Colliderの名前をログに表示(デバッグ用)
        foreach (Collider col in colliders)
        {
            Debug.Log("登録されたCollider: " + col.name);
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        foreach (ContactPoint contact in collision.contacts)
        {
            Debug.Log("衝突したCollider: " + contact.thisCollider.name);
        }
    }

    void OnTriggerEnter(Collider other)
    {
        Debug.Log("トリガーに入ったCollider: " + other.name);
    }
}

ポイント

  • GetComponents<Collider>() を使用して、すべてのColliderを取得
  • collision.contacts[].thisCollider.name を使用して、衝突したColliderを特定
  • OnTriggerEnter() を使用して、トリガーエリアへの進入を検出

(2) 物理衝突とトリガーを分ける

通常の Collider(物理衝突用)と Trigger Collider(範囲検出用)を区別して処理を分ける例です。

void OnCollisionEnter(Collision collision)
{
    foreach (ContactPoint contact in collision.contacts)
    {
        if (contact.thisCollider.name == "BoxCollider")
        {
            Debug.Log("物理衝突: 体に当たった!");
        }
    }
}

void OnTriggerEnter(Collider other)
{
    if (other.name == "SphereCollider")
    {
        Debug.Log("プレイヤーがセンサー範囲に入った!");
    }
}

ポイント

  • contact.thisCollider.name == "BoxCollider"物理衝突を検出
  • other.name == "SphereCollider"トリガー範囲への進入を検出

6. Physics.IgnoreCollision() を使用して特定のColliderを無視

特定の Collider 同士の衝突を無視したい場合は、Physics.IgnoreCollision() を使用できます。

void Start()
{
    Collider boxCollider = GetComponent<BoxCollider>();
    Collider sphereCollider = GetComponent<SphereCollider>();

    // 物理衝突を無視(ただしトリガーイベントは発生する)
    Physics.IgnoreCollision(boxCollider, sphereCollider, true);
}

ポイント

  • Physics.IgnoreCollision() を使うと、特定のCollider間の物理衝突を無効化
  • isTrigger = true なら、トリガーイベントは発生する

7. 注意事項

(1) 同じオブジェクト内のCollider同士が意図せず衝突する場合

  • Unityは同じ GameObject 内の Collider 同士は基本的に衝突しない
  • しかし、親子関係の Collider やスクリプトによる動的変更で衝突することがある
  • Physics.IgnoreCollision() を適切に使用することで回避可能

(2) Rigidbody は1つにする

  • 1つの GameObject複数の Rigidbody を持たせると、物理挙動が不安定になる
  • Rigidbody は親オブジェクトに1つだけ設定 する

8. まとめ

項目内容
1つのGameObjectに複数のColliderを持たせる理由異なる形状の当たり判定を1つのオブジェクトに持たせるため
物理計算の管理Rigidbodyは1つだけ持たせ、Colliderごとに異なる処理を行う
衝突の判別方法collision.contacts[].thisCollider.name を使い、どのColliderが衝突したかを取得
トリガーと物理衝突を分離OnTriggerEnter()OnCollisionEnter() を分けて処理
特定のCollider間の衝突を無視Physics.IgnoreCollision() を使用

9. 結論

  • 1つの GameObject に複数の Collider を持たせることで、より詳細な衝突判定が可能
  • トリガーと物理衝突を分けて管理することで、ゲームロジックを整理しやすい
  • 適切なスクリプトを活用することで、安定した物理挙動を実現できる

Unity,当たり判定

Posted by hidepon