この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: 衝突時の処理
SEOタイトル: Unity 衝突検知 (Collision) 完全ガイド(Collider / Rigidbody / Trigger / Layer Matrix)

この記事の要点
  • 衝突検知は Collider + Rigidbody が必須。両 GameObject に Collider、最低どちらかに Rigidbody
  • 物理衝突: OnCollisionEnter(Collision col) / Stay / Exit
  • すり抜けトリガー: Collider の Is Trigger ON → OnTriggerEnter(Collider other) / Stay / Exit
  • 対象の絞り込みは Layer Collision Matrix または CompareTag
  • 高速移動オブジェクトのすり抜けは Continuous Detection (CCD) で対策

衝突検知が動く条件

Unity で「物にぶつかった」イベントを取るには、最低限3 つの条件が必要です:

  1. 双方の GameObject に Collider が付いている(Box / Sphere / Capsule / Mesh など)
  2. 少なくとも片方に Rigidbody が付いている(Kinematic でも可)
  3. Layer Collision Matrix で衝突が許可されている

Rigidbody が無い静止物どうしは Static Collider 扱いで、物理エンジンが移動しないと見なすため、衝突イベントを発生させません。

Collider の種類

Collider形状コスト用途
Box Collider建物、家具、ブロック
Sphere Colliderボール、爆発範囲
Capsule Colliderカプセル人型キャラ
Mesh Colliderメッシュ形状そのまま不規則な地形(Convex=ON で動的にも使える)
Terrain Collider地形専用Terrain と組
Wheel Collider車輪専用車両物理

OnCollisionEnter / Stay / Exit

物理的にぶつかったときに呼ばれるコールバック。引数の Collision から接触点や相手オブジェクトを取得できます:

using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class BulletCollision : MonoBehaviour
{
    public int damage = 10;

    void OnCollisionEnter(Collision col)
    {
        // 相手の GameObject
        GameObject other = col.gameObject;

        // Tag で判定(推奨: 文字列比較より高速)
        if (other.CompareTag("Enemy"))
        {
            other.GetComponent()?.TakeDamage(damage);
            Destroy(gameObject);  // 弾を消す
        }

        // 接触点情報
        ContactPoint contact = col.contacts[0];
        Vector3 hitPos = contact.point;
        Vector3 hitNormal = contact.normal;

        // 相対速度(強い衝撃の判定など)
        float impact = col.relativeVelocity.magnitude;
        if (impact > 10f)
        {
            // 大ダメージ
        }
    }

    void OnCollisionStay(Collision col)
    {
        // 接触し続けている間、毎 FixedUpdate に呼ばれる
    }

    void OnCollisionExit(Collision col)
    {
        // 離れた瞬間
    }
}

OnTriggerEnter / Stay / Exit(すり抜けトリガー)

Collider の Is Trigger にチェックを入れると物理的な反発はせず、すり抜けながらイベントだけ発火します。「エリアに入ったら〜」「アイテム取得」などに最適:

using UnityEngine;

// アイテム取得トリガーの例
public class ItemPickup : MonoBehaviour
{
    public int value = 10;

    void OnTriggerEnter(Collider other)
    {
        // 引数は Collision ではなく Collider なので注意
        if (other.CompareTag("Player"))
        {
            PlayerInventory inv = other.GetComponent();
            inv?.AddItem(value);
            Destroy(gameObject);
        }
    }

    void OnTriggerStay(Collider other)
    {
        // エリア内に居続ける間(毒沼ダメージ等)
    }

    void OnTriggerExit(Collider other)
    {
        // 離脱
    }
}

Collision と Trigger の使い分け

OnCollision*OnTrigger*
Is TriggerOFFON(どちらか一方で良い)
物理反発ありなし(すり抜け)
引数の型CollisionCollider
接触点情報取れる取れない
用途弾と敵、ボールと壁アイテム、エリア、当たり判定

2D の場合

2D ゲームでは 2D 専用 API を使います。形式は同じです:

  • Collider2D(BoxCollider2D / CircleCollider2D / PolygonCollider2D 等)
  • Rigidbody2D
  • OnCollisionEnter2D(Collision2D col) / OnTriggerEnter2D(Collider2D other)

Layer Collision Matrix

レイヤー単位で「このレイヤーと、このレイヤーは衝突する/しない」を制御できます:

  • Edit > Project Settings > Physics
  • 下部の Layer Collision Matrix でチェックボックス操作
  • 例: 「Enemy」と「EnemyBullet」を OFF にすると、敵が自分の弾に当たらない

CompareTag によるフィルタ

相手の判定はCompareTag を使うのが定石です。== "Tag" よりも高速で、未定義 Tag を渡すと警告も出ます:

// ❌ 遅い(文字列生成 + 比較)
if (other.tag == "Enemy") { ... }

// ✅ 推奨
if (other.CompareTag("Enemy")) { ... }

// 複数 Tag を比較するなら
string t = other.tag;
switch (t)
{
    case "Enemy": ... break;
    case "Boss":  ... break;
}

Physic Material(摩擦と反発)

Collider に Physic Material をアタッチすると、物理的な質感を変えられます:

項目値の例効果
Dynamic Friction0.0 (氷) - 1.0 (ゴム)動いてる物の摩擦
Static Friction0.0 - 1.0止まってる物の摩擦
Bounciness0.0 (落ちて止まる) - 1.0 (永遠に跳ねる)反発係数
Friction CombineAverage / Minimum / Multiply / Maximum2 物体の摩擦合成法
Bounce Combine同上反発合成法

高速移動オブジェクトのすり抜け対策(CCD)

弾丸など高速で動くオブジェクトは、1 フレームに薄い壁を飛び越えて衝突を見落とすことがあります。Rigidbody の Collision Detection を変更:

モードコスト用途
Discrete(既定)通常物体
Continuous高速移動物 → 静止物への当たり
Continuous Dynamic高速移動物 → 高速移動物
Continuous Speculative新方式、回転にも強い

イベントが来ない時のチェックリスト

  1. 双方に Collider があるか
  2. 少なくとも片方に Rigidbody があるか(IsKinematic でも可)
  3. Mesh Collider どうしの場合、片方は Convex か
  4. Layer Collision Matrix で OFF にしていないか
  5. Is Trigger と Collision 用イベントを混同していないか
  6. 関数名のスペルが正しいか(OnTriggerEnterOnTriggerEntered
  7. Time Scale が 0 でないか
  8. Active / Enabled がオフでないか

FAQ

Q: Rigidbody を付けたくない
A: Is Kinematic = true の Rigidbody を付ければ物理影響を受けずに衝突イベントだけ取れます。

Q: OnCollisionEnter は呼ばれるが OnCollisionStay が呼ばれない
A: 接触中の Rigidbody が Sleep 状態になると Stay が止まります。Rigidbody.sleepThreshold を下げるか、毎フレーム小さな力を加えてください。

Q: トリガーを Raycast で取りたい
A: Physics.queriesHitTriggers を ON にするか、Physics.Raycast(..., QueryTriggerInteraction.Collide) を指定。