適当おじさんの適当ブログ

技術のことやゲーム開発のことやゲームのことなど自由に雑多に書き連ねます

Collider 2Dの衝突・侵入判定について

はじめてCollider 2Dコンポーネントを利用して、衝突判定した際に色々悩んだ記憶があるので、自身の知識の整理も兼ねてまとめておきます。以下の章に大別して書いています。

  • 「Collider 2Dについて」
  • 「物体の移動方法について」
  • 「衝突判定について」

今回は、単純な衝突判定のみを取り扱うので、以下については触れません。機会があれば、別の記事として書こうと思います。

  • 「Composite Collider 2D」は今回取り扱いません。複数のColliderが重なった時に、それらのCompositeを合成するものです。
  • Colliderの「Used By Effector」などのパラメータとそれに関する事柄についても取り扱いません。

Collider 2Dについて

Collider 2Dとその種類

GameObjectに Collider 2Dコンポーネント をアタッチすることで、そのGameObjectにいわゆる「当たり判定」が付与できます。

Collider 2Dは、形状別に用意されています。それぞれのColliderは、基本的に「形状 + Collider 2D」という名前がつけられています。緑枠の部分が Collider の「当たり判定」の部分です。

f:id:subarunari:20170630142047p:plain

色々ありますが形状や用途に合ったColliderを選択すれば良いです。複雑な形状のColliderを作りたい場合は、Edge Collider 2D もしくは Polygon Collider 2D が適切かと思います。GameObjectにアタッチされたColliderは、「Edit Collider」ボタンを押すことで編集できます。

Colliderは複数アタッチできます。たとえば次のように「Box Collider 2D」と「Capsule Collider 2D」をそれぞれアタッチしておくこともできます。

f:id:subarunari:20170630095339p:plain:w105

物理シミュレーションの有効化

Colliderの振る舞いを有効にするためには、GameObjectの Physics Simulation が有効になっていなければいけません。GameObjectに、RigidBody 2D をアタッチし、BodyTypeをDynamicとし、simulated パラメータをONにすることで Physics Simulation が有効になります。

f:id:subarunari:20170630011824p:plain:w300

「当たり判定」を有効にするには、Collider 2D と RigidBody 2D の2つのコンポーネントのアタッチ、そして、RigidBody 2Dの simulated パラメータをONにする必要があります。

衝突判定について

is Trigger パラメータについて

f:id:subarunari:20170629230016p:plain:w300

Collider 2Dがアタッチされたオブジェクト同士が接触すると、デフォルトでは 衝突する 挙動を示します。Collider の is Trigger にチェックを入れると、そのオブジェクトは 衝突せずにすりぬける ようになります。後者は、Colliderを領域とみなし、その領域に対する接触判定と考えるとわかりやすいと思います。私はこれを衝突に対して、 「侵入」 と呼んでいます。

イベント発生時のコールバック

「衝突」もしくは「侵入」を検知した際に、専用のコールバックメソッドが呼び出されます。これらのコールバックメソッドをオーバーライドすることで、衝突・侵入時の処理を記載します。このコールバックは、双方のGameObjectで呼び出されます。

f:id:subarunari:20170630160439p:plain

また、Aの is Trigger=ON、Bの is Trigger=OFFとした場合、2つのオブジェクトは衝突せずに侵入します。侵入した際に双方のオブジェクトで OnTriggerEnter2D が呼び出されます。ここで重要なのは、 is Triggerにチェックを入れていないBのコールバックも呼ばれる ということです。

コールバックの種類

検知したイベントに応じて、Enter2D, Stay2D, Exit2D がつくメソッドが呼びだされるようになっています。

衝突時のメソッド 発生条件
OnCollisionEnter2D Colliderを持つオブジェクト同士が衝突した時
OnCollisionStay2D Colliderを持つオブジェクトが接し続けている間、毎フレーム
OnCollisionExit2D 接触状態にあるColliderを持つオブジェクト同士が離れた時
侵入時のメソッド 発生条件
OnTriggerEnter2D Colliderを持つオブジェクトの領域に入った時
OnTriggerStay2D Colliderを持つオブジェクトの領域に入っている時
OnTriggerExit2D Colliderを持つオブジェクトの領域から出た時
具体例

上記メソッドをオーバーライドして、GameObjectに衝突・侵入時の処理を追加します。例では、衝突・侵入したオブジェクトの名前をログとして表示しています。引数には衝突・侵入したオブジェクトが渡されます。

public class Sample : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        Debug.Log("OnTriggerEnter2D: " + other.gameObject.name);
    }

    void OnTriggerStay2D(Collider2D other)
    {
        Debug.Log("OnTriggerStay2D: " + other.gameObject.name);
    }

    void OnTriggerExit2D(Collider2D other)
    {
        Debug.Log("OnTriggerExit2D: " + other.gameObject.name);
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        Debug.Log("OnCollisionEnter2D: " + collision.gameObject.name);
    }

    void OnCollisionStay2D(Collision2D collision)
    {
        Debug.Log("OnCollisionStay2D: " + collision.gameObject.name);
    }

    void OnCollisionExit2D(Collision2D collision)
    {
        Debug.Log("OnCollisionExit2D: " + collision.gameObject.name);
    }
}
コンポーネントとコールバックを "2D" で合わせる

2D用のRigidBody、Colliderとそれに関するコールバックすべてに 2D がついていることを確認してください。2Dがついていないものは3D用のコンポーネントです。2Dと3Dで異なるコンポーネントとして用意されています。2Dもしくは3Dで統一していないと動作しません。

さいごに

以上、Collider 2D を用いた衝突判定のもっとも基本的(と思われる)な部分について記載しました。+αの内容は別の記事にまとめていこうと思います。何か間違い等あれば、ぜひコメントいただければと思います。

Polygon Collider 2Dで利用しているSpriteや、衝突・侵入判定の図で利用しているSpriteは以下のAssetを利用しています。プロトタイプを作る際などに便利なのでぜひぜひ。