◀ 2.

Unity Script error: OnCollisionEnter の対処

この記事の要点
  • 「Script error: OnCollisionEnter This message parameter has to be of type: Collision」は引数の型が違うときに出る
  • 正しい形は void OnCollisionEnter(Collision collision)。よくある誤りは Collider 型を書いてしまうこと
  • OnTrigger 系は Collider、OnCollision 系は Collision。2D では Collision2D / Collider2D
  • このエラーが出ている間、そのメソッドは呼ばれず無視される(コンパイルエラーではないので見落としやすい)
  • 型を直しても呼ばれない場合は、Rigidbody の有無・isTrigger・2D と 3D の混在を確認する

エラー内容

Script error: OnCollisionEnter
This message parameter has to be of type: Collision
The message will be ignored.

Unity のコンソールにこのメッセージが出た場合、衝突時に呼ばれるはずの OnCollisionEnter が実行されていません。C# のコンパイルは通るため再生自体はできますが、「ぶつかっても何も起きない」という症状になります。

原因: OnCollisionEnter の引数の型が間違っている

OnCollisionEnter は Unity が名前で探して呼び出す「メッセージ関数」です。Unity は関数名だけでなく引数の型も確認しており、型が想定と違うと呼び出しをあきらめて上のメッセージを出します。

最も多いのは、引数を Collision ではなく Collider にしてしまうケースです。名前が 1 文字違いで、補完でも両方が候補に出るため、取り違えやすくなっています。

// NG: 引数が Collider になっている(メッセージは無視される)
void OnCollisionEnter(Collider other)
{
    Debug.Log("hit");
}

// OK: 引数は Collision
void OnCollisionEnter(Collision collision)
{
    Debug.Log("hit: " + collision.gameObject.name);
}

このほか、GameObject や独自クラスを引数にしている、引数を 2 つ書いているといった場合も同じエラーになります。引数は「Collision 型を 1 つ」または「引数なし」のどちらかにしてください(引数なしでも呼び出し自体は行われます)。

対処法

  1. コンソールのメッセージをダブルクリックするか、該当スクリプトを開く
  2. OnCollisionEnter(および OnCollisionStay / OnCollisionExit)の引数を Collision 型に直す
  3. 関数内で other.gameObject のように Collider として使っていた部分を、collision.gameObject や collision.collider に書き換える
  4. 保存して Unity に戻り、再生して衝突時にログが出るか確認する

Collision 型からは、ぶつかった相手の Collider(collision.collider)、GameObject(collision.gameObject)、接触点(collision.contacts や collision.GetContact(0))、衝突の相対速度(collision.relativeVelocity)などが取れます。Collider 型より情報が多いのは、物理的な「衝突」の結果を表すオブジェクトだからです。

衝突系メッセージの引数の型一覧

同じ種類の取り違えは Trigger 系や 2D 版でも起きます。次の表で確認してください。

メソッド引数の型呼ばれるタイミング
OnCollisionEnter / Stay / ExitCollision3D の物理的な衝突の開始・継続・終了
OnTriggerEnter / Stay / ExitCollider3D で isTrigger の Collider に入った・中にいる・出た
OnCollisionEnter2D / Stay2D / Exit2DCollision2D2D の物理的な衝突
OnTriggerEnter2D / Stay2D / Exit2DCollider2D2D の Trigger への出入り
OnControllerColliderHitControllerColliderHitCharacterController が Move 中に何かに当たった

覚え方としては、「Trigger はすり抜ける領域なので相手の Collider だけ渡される」「Collision は実際にぶつかった結果なので接触情報を含む Collision が渡される」と理解しておくと混乱しにくくなります。

型を直しても OnCollisionEnter が呼ばれないとき

エラーが消えたのに衝突が検知されない場合は、物理の設定側に原因があります。

  • Rigidbody がない: 衝突メッセージが発生するには、ぶつかる 2 つのうち少なくとも一方に Rigidbody が必要。両方が Collider だけの静的オブジェクトでは呼ばれない
  • isTrigger がオンになっている: どちらかの Collider で Is Trigger がオンだと、OnCollision 系ではなく OnTrigger 系が呼ばれる
  • 2D と 3D の混在: BoxCollider2D と Rigidbody(3D)のように 2D 用と 3D 用を混ぜると、互いに衝突しない。2D なら OnCollisionEnter2D を使う
  • Kinematic 同士: 両方が Is Kinematic の Rigidbody だと、通常は衝突メッセージが発生しない
  • レイヤー設定: Project Settings の Physics にある Layer Collision Matrix で、該当レイヤー同士の衝突が無効になっていないか
  • スクリプトの付け先: スクリプトが Collider を持つ GameObject(または Rigidbody を持つ親)に付いているか
  • 高速移動のすり抜け: 速すぎる物体は 1 フレームで相手を通り抜けることがある。Rigidbody の Collision Detection を Continuous 系に変える

確認方法

まずは最小構成で、衝突が検知されているかをログで確かめるのが確実です。

using UnityEngine;

public class HitCheck : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        Debug.Log($"Collision: {name} -> {collision.gameObject.name}");
    }

    void OnTriggerEnter(Collider other)
    {
        Debug.Log($"Trigger: {name} -> {other.gameObject.name}");
    }
}

このスクリプトを付けて再生し、どちらのログが出るか(または何も出ないか)を見れば、型の問題なのか、Trigger 設定や Rigidbody の問題なのかを切り分けられます。

関連

子ページ

子ページはありません

同階層のページ
  1. Non-convex MeshCollider with non-kinematic Rigidbody is no longer supported in Unity 5.
  2. Script error: OnCollisionEnter

最近更新/作成されたページ