【Unity】OnCollisionEnter2Dが呼ばれない!2D物理演算の衝突判定における原因と解決法

Unityにおける2Dゲーム開発において、オブジェクト同士の当たり判定(衝突判定)は非常に重要な要素です。
しかし、実装を進める中で「コードは正しいはずなのに OnCollisionEnter2D メソッドが呼ばれない(発火しない)」というトラブルは、多くの開発者が直面する典型的なつまずきポイントです。

本記事では、CircleCollider2Dradius 設定ミスといった初歩的な見落としから、Unityの物理演算システム(Physics 2D)の仕様に基づいた前提条件まで、OnCollisionEnter2D が機能しない際の原因と具体的な解決策を技術的な観点から解説します。

目次

OnCollisionEnter2Dが発火するための前提条件

Unityの2D物理演算エンジンが「衝突」を検知し、スクリプト上の OnCollisionEnter2D を呼び出すためには、いくつかの厳密な前提条件が満たされている必要があります。まずは以下の基本構成がオブジェクトに適用されているかを確認してください。

必須コンポーネントの構成
  1. 衝突する双方のオブジェクトに、何らかの Collider2D(BoxCollider2DやCircleCollider2Dなど)がアタッチされていること。
  2. 衝突する少なくとも一方のオブジェクトに、Rigidbody2D がアタッチされていること。
  3. 双方の Collider2D コンポーネントにおいて、**Is Trigger プロパティが false(チェックなし)**に設定されていること。

特に Rigidbody2D の設定は重要です。
双方のオブジェクトが Rigidbody2D を持たない場合、または両方の「Body Type」が Static(静的)に設定されている場合、Unityはそれらを動かない背景として扱い、衝突判定の計算を行いません。

よくある原因1:Collider2Dのサイズ(Radiusなど)が極端に小さい

OnCollisionEnter2D が呼ばれない原因として非常に多いのが、インスペクター上での「Colliderサイズの初期設定による未調整」です。

例えば、円形のオブジェクトに CircleCollider2D をアタッチした際、プロパティである Radius(半径)の数値が初期値のままになっており、実際のオブジェクト(Sprite)の見た目に対して当たり判定の範囲が極端に小さくなっているケースがあります。

【注意点】
見た目と物理判定の乖離 画面上ではオブジェクト同士が明確に重なって(ぶつかって)いるように見えても、内部の物理演算においては Collider の境界線同士が全く接触していないため、OnCollisionEnter2D はトリガーされません。

【解決策】
対象オブジェクトのインスペクターを開き、Collider2D コンポーネントの Edit Collider ボタンを押下して、シーンビュー上で当たり判定の緑色の枠線が Sprite の輪郭に沿うようにサイズ(RadiusやSize)を適切に拡大・調整してください。

よくある原因2:Is Triggerが有効になっている

当たり判定には、物理的な反発を伴う「Collision(衝突)」と、領域への侵入を検知する「Trigger(通過)」の2種類が存在します。

インスペクター上の Collider2D にある Is Trigger にチェックが入っている場合、物理的な衝突は発生せず、オブジェクト同士はすり抜けます。
この状態では OnCollisionEnter2D ではなく、OnTriggerEnter2D メソッドが呼ばれる仕様となっています。

物理的な壁や床、キャラクター同士のぶつかり合いを実装したい場合は、必ず Is Trigger を無効化(チェックを外す)してください。

よくある原因3:レイヤー衝突マトリックス(Layer Collision Matrix)の設定

コンポーネントの設定に問題がない場合、プロジェクト全体の物理演算設定によって特定のレイヤー間の衝突が意図的に無視されている可能性があります。

Unityには、特定のレイヤー同士の当たり判定を制御する「Layer Collision Matrix」という機能があります。

【確認手順】
1. メニューバーから Edit > Project Settings を開く。
2. 左側のタブから Physics 2D を選択する。
3. インスペクター下部にある Layer Collision Matrix を確認する。

ここで、衝突させたいオブジェクトに割り当てられているレイヤー同士の交差部分のチェックボックスが外れている場合、衝突判定は行われません。
必要な箇所にチェックが入っているかを確認してください。

よくある原因4:Rigidbody2Dのスリープ状態

Unityの物理演算エンジンは、パフォーマンス最適化のために、一定時間動きのない Rigidbody2D を「スリープ状態(Sleeping Mode)」に移行させます。
スリープ状態のオブジェクトに対して、Rigidbody2D を持たない(あるいはKinematicな)オブジェクトをスクリプトで直接座標移動(Transform.positionの変更など)させてぶつけた場合、物理演算エンジンが衝突を検知できず、OnCollisionEnter2D が呼ばれないことがあります。

【対策】
Rigidbody2D コンポーネントの Sleeping ModeStart Awake から Never Sleep に変更することでスリープを無効化できます。
ただし、パフォーマンスに影響を与える可能性があるため、基本的には Transform による直接移動ではなく、Rigidbody2D の velocityAddForce を用いた物理的な移動処理を実装することが推奨されます。

OnCollisionトラブルシューティング・チェックリスト

OnCollisionEnter2D が呼ばれずに処理が止まってしまった場合は、以下の項目を順に確認することで、大半の問題を解決することが可能です。

・メソッド名のスペルや引数が間違っていないか(例:Collision ではなく Collision2D になっているか)
・双方に Collider2D がアタッチされ、適切なサイズ(Radius等)が設定されているか
・少なくとも一方に Rigidbody2D がアタッチされているか
・双方の Is Trigger のチェックが外れているか
Project SettingsLayer Collision Matrix でレイヤー間の衝突が許可されているか
・Z軸(奥行き)の座標がずれていないか(2DであってもZ座標が異なると衝突しない場合があります)

当たり判定の実装は、スクリプトの正確性だけでなく、エディタ上のコンポーネント設定や物理演算エンジンの仕様理解が不可欠です。
本記事のチェックポイントを参考に、プロジェクトの設定を見直してみてください。

楽天ブックス
¥2,959 (2026/02/26 00:16時点 | 楽天市場調べ)
トップカルチャーnetクラブ
¥2,959 (2026/02/26 00:17時点 | 楽天市場調べ)

そのほかのUnity記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

はじめまして、秋月なるです。
アラフォー会社員で、スマホアプリ/ゲーム/AIが好き。新しいものを見ると触りたくなるタイプで、スマホやウェアラブル等ガジェットが好きですが、よく買ったあとに「思ってたのと違う…」をやりがち。
ブログ投稿は趣味の1つなので、ゆるく続けていこうと思います。

目次