Unityの衝突判定まとめ

こんにちは。
趣味でUnityを使ってゲームを作っています。
Unityについては本当に趣味程度なので、ブログでアウトプットしながら、
理解を深めていきたいと思います。

今回は衝突判定についてです。

環境

macOS Mojave 10.14
Unity 2017 1.1

衝突判定の種類

Unityの衝突判定には大きく2種類のメソッドが用意されています。
1つはOnCollision系でもう1つはOnTrigger系です。
順に説明していきます。

ざっくり言うと、衝突時に実際に物体同士をぶつけたい場合はOnCollisionを使い、
衝突判定だけで実際にはぶつからない(つまりすり抜けてOKな)場合はOnTriggerを使います。

OnCollision系

衝突時に跳ね返るなどの衝突モーションをさせたい時はこちらを使います。
例えば、ボールが壁にぶつかった時の衝突やボール同士の衝突などに使います。

準備

まず衝突させたい物体には以下が必要です。

  • Collider(is Triggerのチェックは付けない)
  • Rigidbodyコンポーネント

ColliderはBox Colliderなどの衝突判定するための範囲です。
ColliderのisTriggerにチェックを付けるとその物体は衝突をしなくなります。
つまり他の物体をすり抜けるようになります。
チェックを付けた場合はOnCollision系の関数が効かないので注意しましょう。

また両方の物体がRigidbodyコンポーネントのisKinematicにチェックが付いている場合なども呼ばれません。
詳しくは公式のリファレンスに書いてあるので気になる人は呼んでみてください。
https://docs.unity3d.com/ja/current/Manual/CollidersOverview.html

使い方

OnCollision系には以下の関数があります。

コールバック 呼び出されるタイミング
OnCollisionEnter 他のColliderやRigidbodyオブジェクトに触れた時に呼び出される
OnCollisionExit 他のColliderやRigidbodyオブジェクトに離れた時に呼び出される
OnCollisionStay 他のColliderやRigidbodyオブジェクトに触れ続けている時に呼び出される

以下のようにして使います。

void OnCollisionEnter(Collision other)
{
    Debug.Log(other.gameObject.name);
}

引数はCollisionとなり、Collision.gameObjectで衝突したオブジェクトを取得することもできます。

OnTrigger系

衝突時に他の物体に影響を与えたくない時はこちらを使います。
例えばアイテムやセーブポイントなどに使います。

準備

衝突させたい物体には以下が必要です。
– Collider(is Triggerのチェックを付ける)
– Rigidbodyコンポーネント

OnTrigger系を使う場合は必ずColliderのisTriggerにチェックを入れる必要がある点に気をつけましょう。

使い方

OnTrigger系には以下の関数があります。

コールバック 呼び出されるタイミング
OnTriggerEnter 他のColliderやRigidbodyオブジェクトに触れた時に呼び出される
OnTriggerExit 他のColliderやRigidbodyオブジェクトに離れた時に呼び出される
OnTriggerStay 他のColliderやRigidbodyオブジェクトに触れ続けている時に呼び出される

基本的にCollisionの部分がTriggerに変わっただけです。

以下のようにして使います。

void OnTriggerEnter(Collider other)
{
    Debug.Log(other.gameObject.name);
}

気をつけて欲しいのはOnCollision系では引数がCollisionだったのに対し、
OnTrigger系ではColliderを使う点です。

衝突した対象の判定

実際に使ってみると何に当たったのかで、
処理を分けたいということが生じます。

そこでタグを利用します。

例えば壁に当たった場合だけこのオブジェクトを消したいといった場合には、
まず壁となるオブジェクトにタグを付けます。
inspectorの一番上にあるTagからaddTagを選択し、「Wall」というタグを作ります。

unity_collision01

そして、OnCollisionEnterではtagを利用して判別を行います。

void OnCollisionEnter(Collision other)
{
    Debug.Log(other.gameObject.tag);
    if (other.gameObject.tag == "Wall")
    {
        Destroy(this.gameObject);
    }
}

OnTrigger系でも同様です。
ただしOnTriggerの場合はCollider.tagで取得することができます。

まとめ

衝突時に衝突した物体に影響を与える場合はOnCollision系を使い、
衝突時に衝突した物体に影響を与えず、すり抜ける場合はOnTrigger系を使うということだけ
覚えておきましょう。

参考サイト

【Unity】RigidbodyのCollision Detection(衝突の検知)を変えて実験

UnityのRigidbodyとColliderで衝突判定

【Unity】RigidbodyのIsKinematic(物理演算の影響の有無)を変えて実験