てんちょーの技術日誌

自分がつまづいたこととかメモ

【Unity】 衝突判定について整理してみた C#

ユニティちゃんライセンス

このアセットは、『ユニティちゃんライセンス』で提供されています。このアセットをご利用される場合は、『キャラクター利用のガイドライン』も併せてご確認ください。

Unityを勉強している上で困ったのが衝突判定についてです。

いくら簡単に実装できるよ、そしてここをこうするだけでこの関数で...と言われても分かりにくいところが 個人的にあったので整理してみました。

今回テスト用に作成したProjectのリンク貼るので参考になればと思います(間違っていれば教えてください

projectのリンク

https://www.dropbox.com/sh/wd0s8apkpwbffkp/AAD1I-xMS_rOPVE3VQK-jqtQa?dl=0

衝突させよう

cube2つとplaneだけを用いて実験したいと思います。 用意したobjectとその変更点、追加点を。

cube1

  • Position(0, 0.5, 0)
  • Scale(1.5, 0, 0)
  • (Rigidbody)

cube2

  • Position(0, 15, 0)
  • Rigidbody

plane

です。cube1のRigidbodyはありなしで結果が変わるのでどっちも見てみるといいかも。

MainCameraは好きに調整してください。

こんな感じになりました。 f:id:shop_0761:20150504131646p:plain

Script

それぞれに追加するスクリプト載せておきます。 Debug.Logの中身(cube1 cube2 plane)が違うだけですが、コピペできるように一応3つ載せます。

cube1Script

using UnityEngine;
using System.Collections;

public class cube1Script : MonoBehaviour {

    // Use this for initialization
    void Start () {
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    //Box Collider -> Is Trigger OFF
    void OnCollisionEnter(Collision collision) {
        Debug.Log("cube1 hit OnCollisionEnter with " + collision.gameObject);
    }

    void OnCollisionExit(Collision collision) {
        Debug.Log("cube1 hit OnCollisionExit with " + collision.gameObject);
    }
    
    void OnCollisionStay(Collision collision) {
        Debug.Log("cube1 hit OnCollisionStay with " + collision.gameObject);
    }

    //Box Collider -> Is Trigger ON
    void OnTriggerEnter(Collider collider){
        Debug.Log("cube1 hit OnTriggerEnter with " + collider.gameObject);
    }

    void OnTriggerExit(Collider collider){
        Debug.Log("cube1 hit OnTriggerExit with " + collider.gameObject);
    }
    
    void OnTriggerStay(Collider collider){    
        Debug.Log("cube1 hit OnTriggerStay with " + collider.gameObject);
    }
}

cube2Script

using UnityEngine;
using System.Collections;

public class cube2Script : MonoBehaviour {

    // Use this for initialization
    void Start () {
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    //Box Collider -> Is Trigger OFF
    void OnCollisionEnter(Collision collision) {
        Debug.Log("cube2 hit OnCollisionEnter with " + collision.gameObject);
    }

    void OnCollisionExit(Collision collision) {
        Debug.Log("cube2 hit OnCollisionExit with " + collision.gameObject);
    }
    
    void OnCollisionStay(Collision collision) {
        Debug.Log("cube2 hit OnCollisionStay with " + collision.gameObject);
    }

    //Box Collider -> Is Trigger ON
    void OnTriggerEnter(Collider collider){
        Debug.Log("cube2 hit OnTriggerEnter with " + collider.gameObject);
    }

    void OnTriggerExit(Collider collider){
        Debug.Log("cube2 hit OnTriggerExit with " + collider.gameObject);
    }
    
    void OnTriggerStay(Collider collider){    
        Debug.Log("cube2 hit OnTriggerStay with " + collider.gameObject);
    }

}

planeScript

using UnityEngine;
using System.Collections;

public class cube2Script : MonoBehaviour {

    // Use this for initialization
    void Start () {
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    //Box Collider -> Is Trigger OFF
    void OnCollisionEnter(Collision collision) {
        Debug.Log("cube2 hit OnCollisionEnter with " + collision.gameObject);
    }

    void OnCollisionExit(Collision collision) {
        Debug.Log("cube2 hit OnCollisionExit with " + collision.gameObject);
    }
    
    void OnCollisionStay(Collision collision) {
        Debug.Log("cube2 hit OnCollisionStay with " + collision.gameObject);
    }

    //Box Collider -> Is Trigger ON
    void OnTriggerEnter(Collider collider){
        Debug.Log("cube2 hit OnTriggerEnter with " + collider.gameObject);
    }

    void OnTriggerExit(Collider collider){
        Debug.Log("cube2 hit OnTriggerExit with " + collider.gameObject);
    }
    
    void OnTriggerStay(Collider collider){    
        Debug.Log("cube2 hit OnTriggerStay with " + collider.gameObject);
    }

}

OnCollision~のやつは障害物とかとの衝突時の処理で、OnTrigger~は衝突検出のみに使う。 基本的な衝突判定は前者でいいはず。後者は衝突するけど、その衝突演算はせずに関数を呼び出すっぽい。 ~Enterは接触した瞬間、~Exitは離れる瞬間、~Stayは接触してる間中と思ってくれれば。

でScriptができたらそれぞれのObjectにドラッグ&ドロップもしくはAdd Componentから設定してください。

動かしてみる

構造的には上からcube2が降ってくる。それだけ。

そのときのLogを見て分析しようという魂胆です。

Logの見方として

(衝突元のobject) hit (そのときの関数) with (衝突先のobject)

という具合です。(順番に意味はありません 見やすそうな順にしただけ)

では実際に見てみると f:id:shop_0761:20150504131706p:plain

衝突元と衝突先で同じ関数が同じ回数呼ばれていますね。ということはどっちに関数を設定してもいいのか!

それは知らなかった。ちゃんとEnterとExitは衝突した回数だけだし、stayだけ数が伸びてるのも納得。

あとはTrigger設定したり、cube1のRigidbodyを消したりして様子見てみるといいかも。 時間があればCharacterControllerについても実験したい。

参考

qiita.com

続き

shop-0761.hatenablog.com