ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

Unity - ContactPoint:オブジェクトが衝突した位置の情報を取得する

初めに

 ContactPoint や Collision.GetContact を使うことで、オブジェクトと衝突したときに発生する位置や法線ベクトルなどの情報を取得することができます。本記事では、衝突が発生した接触点の情報の取得の仕方をまとめます。

ContactPoint

 ContactPoint は、Unity の Collision クラスで使用される構造体です。この構造体は、オブジェクト同士の接触情報を格納します。

変数 説明
point (Vector3)接触した位置
normal (Vector3)接触点の法線ベクトル
thisCollider (Collider)最初に接触したコライダー
otherCollider (Collider)接触している他のコライダー
separation (float)互いにめり込む可能性があるコライダー間の距離

Collision.GetContact 関数、Collision.GetContacts 関数

Collision.GetContact 関数

 指定したインデックスの接触情報を返します。通常、1つの接触点しか必要ない場合は、インデックス0を使用します。

public ContactPoint GetContact (int index);

(例)

void OnCollisionEnter(Collision collision)
{
     //接触した地点のContactPointを取得
    ContactPoint contact = collision.GetContact(0);

    //接触した位置を取得
    Vector3 contactPoint = contact.point;
    GameObject otherObject = contact.otherCollider.gameObject;
}
Collision.GetContacts 関数

 接触情報の配列を返します。接触情報の数が不定である場合や、複数の接触点に対して処理を行いたい場合に使用します。

public int GetContacts (ContactPoint[] contacts);

(例)

void OnCollisionEnter(Collision collision)
{
    ContactPoint[] contacts = collision.contacts;

    foreach (ContactPoint contact in contacts)
    {
        Vector3 contactPoint = contact.point;
        GameObject otherObject = contact.otherCollider.gameObject;
    }
}
Collision.contactCount

 Collision.contactCount を使うことで、接触点の個数を取得することができます。

public int contactCount ;

 接触点が存在するかの判定など、Collision.GetContact 関数、Collision.GetContacts 関数と一緒に使うことがあります。

(例)

void OnCollisionEnter(Collision collision)
{
    if (collision.contactCount > 0)
    {
        // 衝突したオブジェクトに接触点が存在する場合の処理
        Debug.Log("接触点の数: " + collision.contactCount);

        ContactPoint contact = collision.GetContact(0);
        Vector3 contactPoint = contact.point;
        GameObject otherObject = contact.otherCollider.gameObject;
    }
    else
    {
        // 衝突したオブジェクトに接触点が存在しない場合の処理
        Debug.Log("接触点がありません");
    }
}

2d の場合

 Collision2D にも、Collision2D.GetContact 関数、Collision2D.GetContacts 関数があります。ただし、返す変数は ContactPoint ではなく ContactPoint2D になります。

(例)

//OnCollisionEnter2D, Collision2Dであることに注意
void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.contactCount > 0)
    {
        // 衝突したオブジェクトに接触点が存在する場合の処理
        ContactPoint2D contact = collision.GetContact(0);  //ContactPoint2D
        Vector2 contactPoint = contact.point;  //Vector3ではなく, Vector2
        GameObject otherObject = contact.collider.gameObject;
    }
    else
    {
        // 衝突したオブジェクトに接触点が存在しない場合の処理
        Debug.Log("接触点がありません");
    }
}

IsTrigger が有効の場合

 Collider.IsTrigger が有効の場合、void OnTriggerEnter(Collider other) が使用され、物理的な衝突情報は提供されません。試行錯誤しましたが、Collider から Collision を取得する方法が見つからず、IsTrigger が有効の場合に ContactPoint を使用する方法は分かりませんでした。