親オブジェクトにRigidbody、子オブジェクトにColliderを持たせる設計に関する技術資料


1. 概要

本資料では、親にRigidbodyを付与し、子にColliderのみを設定する構成のメリットや実装方法について解説します。
この構成は、複数の当たり判定(Collider)を持つオブジェクトで、物理シミュレーションや衝突判定を効率的に管理するために用いられます。


2. 基本構造と考え方

[親オブジェクト]

  • Rigidbodyを持つ(物理計算の基準)
  • Transformを制御し、全体の動きを管理する

[子オブジェクト]

  • Colliderのみを持つ
  • 部位ごとの衝突判定を行う
  • 親のRigidbodyの動きに従う

3. 利点

[物理演算の統一管理]

  • Rigidbody が親オブジェクトにあることで、オブジェクト全体が一体となって動作する
  • Rigidbody を持つオブジェクトごとに物理計算が行われるため、無駄な計算が発生しない

[部位ごとの衝突判定]

  • 子オブジェクトごとに異なる Collider を設定することで、どの部分が衝突したかを判別可能
  • collision.contacts[].thisCollider.name を用いることで、衝突箇所を特定できる

[管理の容易さ]

  • 子オブジェクトに Rigidbody を付けないことで、物理計算の負荷を削減
  • 一部の子オブジェクトのみ Physics.IgnoreCollision() を用いて衝突無視が可能

4. シーン構成例

Player (親オブジェクト) → Rigidbody [○]
  ├─ Head (子オブジェクト) → BoxCollider [□]
  ├─ Body (子オブジェクト) → CapsuleCollider [□]
  • Player: Rigidbody を持ち、物理計算の基準となる
  • Head/Body: それぞれ Collider を持ち、個別の衝突判定を行う

5. コードサンプル

[1] 親オブジェクト(Player)にRigidbodyを設定

親オブジェクトで Rigidbody を持ち、子オブジェクトの Collider との衝突を管理するスクリプトを作成します。

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Rigidbody rb;

    void Start()
    {
        // Rigidbodyの取得
        rb = GetComponent<Rigidbody>();
        rb.mass = 1.0f;
        rb.drag = 0.5f;
        rb.useGravity = true;
    }

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

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

[ポイント]

  • OnCollisionEnter() でどの Collider が衝突したかを判別
  • OnTriggerEnter() でトリガー範囲内に入ったことを検出
  • thisCollider.name で衝突した子オブジェクトを特定

[2] 子オブジェクト(Colliderのみ)

子オブジェクトには Collider のみを設定し、親の Rigidbody に依存させます。

using UnityEngine;

public class BodyPartCollider : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        Debug.Log(gameObject.name + " に衝突した: " + collision.gameObject.name);
    }

    void OnTriggerEnter(Collider other)
    {
        Debug.Log(gameObject.name + " にトリガー衝突: " + other.gameObject.name);
    }
}

[ポイント]

  • gameObject.name を使うことで、衝突した子オブジェクトの名前を特定できる
  • OnCollisionEnter()OnTriggerEnter() を使うことで、部位ごとの処理が可能

[3] Physics.IgnoreCollision() を使って一部の当たり判定を無視

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

void Start()
{
    Collider headCollider = transform.Find("Head").GetComponent<Collider>();
    Collider bodyCollider = transform.Find("Body").GetComponent<Collider>();

    // 頭と体の内部的な衝突を無視する
    Physics.IgnoreCollision(headCollider, bodyCollider, true);
}

[ポイント]

  • Physics.IgnoreCollision() を使用すると、特定の部位間での衝突を無視できる

6. 注意事項

[子オブジェクトに Rigidbody を追加しない]

  • Rigidbody は親オブジェクトのみに設定するのが基本
  • 子に Rigidbody を設定すると、意図しない動きが発生する可能性がある
  • 例外として、「独立して動くパーツ(剣・落下アイテム)」などは子オブジェクトにも Rigidbody を追加

[衝突が2回検出される場合]

  • 子オブジェクトの ColliderOnCollisionEnter() を設定すると、親と子の両方で衝突が検出される場合がある
  • collision.contacts[].thisCollider.name を使って判別することで回避可能

7. まとめ

  • 構成の基本:
    • 親オブジェクトに Rigidbody を配置
    • 子オブジェクトに Collider を配置
    • Rigidbody が親にあることで、物理挙動は一体として管理される
  • 衝突判定の詳細:
    • collision.contacts[].thisCollider.name を利用することで、どの部位が衝突したかの判別が可能となり、細かい処理や演出が実現できる。

この構成により、複数部位にわたる衝突判定を効率的に行い、かつ物理挙動の統一管理を実現することが可能 となります。

Unity,当たり判定

Posted by hidepon