【Unity当たり判定】"OnCollision"と"OnTrigger"の違いを徹底解説
はじめに
"OnCollision"と"OnTrigger"の違い
Unityの当たり判定、"OnCollision"と"OnTrigger"は、よく「どっち使うんだったっけ?」ってなる(なりますよね?)。
簡単に…
① ぶつかった!を感知する当たり判定・・・OnCollisionEnter
② すり抜けた!を感知する当たり判定・・・OnTriggerEnter
ぶつコリ、すりトリ。
そのまんまやけど、、、なんもないよりは覚えやすい、、、?
いいの思いついたらこっそり更新しときます(思いつくまでに普通に覚えそう)。
で、で、で、本題。
どっちの当たり方を感知したいのか?で、関数の書き方やコライダーの設定がちょっと変わってくるので、そのへんを解説していきまーす!
ぶつかった!を感知したい場合
どのコンポーネントが必要?
【 Colliderコンポーネント 】
ぶつかる相手とぶつかられる相手、両方のオブジェクトにColliderコンポーネントがアタッチされている必要がある。
また、物体同士がすり抜けないよう、ColliderコンポーネントのIsTriggerのチェックを外しておく(トリガーモード無効)。
【 Rigidbodyコンポーネント 】
ぶつかる相手とぶつかられる相手、どちらかのオブジェクト(両方でもOK)にRigidbodyコンポーネントがアタッチされている必要がある。
スクリプトはどう書く?
OnCollisionEnter(Collision collision)関数を用意し、そこでぶつかったときの処理を書く(この関数はStart()やUpdate()内に書かない。書くことないんちゃうかな、あんま自信はないけど)。
public class ExampleClass : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
void OnCollisionEnter(Collision collision)
{
//ぶつかったときの処理
}
}
で、ちょっと細かいけど、私が後から知って、「あ~なるほど」って思ったこと。
↓↓↓↓↓↓↓↓↓↓↓↓
この関数は、ぶつかった「ゲームオブジェクト」の情報を直接取得するのではなく、ぶつかった「コリジョン」の情報を取得する(コリジョンは、衝突した相手のコライダーや、接触点、衝突の力など様々な衝突に関する情報をもつ)。
なので、ゲームオブジェクトの情報を扱いたい場合は、ぶつかったコリジョンから辿って、ゲームオブジェクト情報を取得する感じになる。
(これを分かってなくて、「なんでいちいち?!」って思っちゃってた。)
void OnCollisionEnter(Collision collision)
{
// 衝突したゲームオブジェクトの名前を取得
string objectName = collision.gameObject.name;
Debug.Log("Collided with: " + objectName);
}
※ちなみのちなみに、整理しておくと、
OnCollisionEnter はぶつかった相手の コリジョン情報 を取得、
OnTriggerEnter はすり抜けた相手の コライダー情報 を取得する。
例えば、コライダー にアクセスしたい場合、
OnTriggerEnter(Collider other) は、other がすでに コライダー であるため、直接アクセス可能。
一方、
OnCollisionEnter(Collision collision) の場合、collision は コリジョン情報 なので、コライダーにアクセスするには、コリジョンから辿っていく必要がある(書き方としては collision.collider )。
OnCollisionEnter使用例1
【やりたいこと】
プレイヤーが障害物にぶつかったら、プレイヤーが爆発する処理。
ぶつかるオブジェクト:プレイヤー
ぶつかられるオブジェクト:障害物
【スクリプト例】
public class SampleCollision: MonoBehaviour
{
public GameObject explosionPrefab; // 爆発エフェクトのプレハブ
void OnCollisionEnter(Collision collision)
{
// 障害物にぶつかったかどうかを確認
if (collision.gameObject.CompareTag("Obstacle"))
{
// プレイヤーの位置で爆発エフェクトを生成
Instantiate(explosionPrefab, transform.position, Quaternion.identity);
// プレイヤーオブジェクトを破壊
Destroy(gameObject);
}
}
}
※上記のスクリプトでいうと、爆発エフェクトのプレハブをスクリプトにアタッチすることを忘れずに!
すり抜けた!を感知したい場合
どのコンポーネントが必要?
【 Colliderコンポーネント 】
すり抜ける相手とすり抜けられる相手、両方のオブジェクトにColliderコンポーネントがアタッチされている必要がある。
また、物体同士がすり抜けるよう、ColliderコンポーネントのIsTriggerのチェックをつけておく(トリガーモード発動!!)。
【 Rigidbodyコンポーネント 】
すり抜ける相手とすり抜けられる相手、どちらかのオブジェクト(両方でもOK)にRigidbodyコンポーネントがアタッチされている必要がある。
スクリプトはどう書く?
OnTriggerEnter(Collider other)関数を用意し、そこですり抜けた時の処理を書く(この関数はStart()やUpdate()内に書かない。書くことないのでは、、、あんまり自信はないけど)。
public class ExampleClass : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
void OnTriggerEnter(Collider other)
{
//すり抜けたときの処理
}
}
で、ちょっと細かいけど、私が後から知って、「あ~なるほど」って思ったことを共有します(※「ぶつかった!を感知したい場合」を読んだ方は飛ばしてください。ほぼ同じ内容です!)。
この関数は、すり抜けた「ゲームオブジェクト」の情報を直接取得するのではなく、すり抜けた「コライダー」の情報を取得する。
なので、ゲームオブジェクトの情報を扱いたい場合は、ぶつかったコライダーから辿って、ゲームオブジェクト情報を取得する感じになる。
(これを分かってなくて、「なんでいちいち?!」って思っちゃってた。)
void OnTriggerEnter(Collider other)
{
// トリガーゾーンに入ってきたゲームオブジェクトの名前を取得
string objectName = other.gameObject.name;
Debug.Log("Entered trigger zone: " + objectName);
}
※ちなみのちなみに、整理しておくと、
OnCollisionEnter はぶつかった相手の コリジョン情報 を取得、
OnTriggerEnter はすり抜けた相手の コライダー情報 を取得する。
例えば、コライダー にアクセスしたい場合、
OnTriggerEnter(Collider other) は、other がすでに コライダー であるため、直接アクセス可能。
一方、
OnCollisionEnter(Collision collision) の場合、collision は コリジョン情報 なので、コライダーにアクセスするには、コリジョンから辿っていく必要がある(書き方としては collision.collider )。
OnTriggerEnter使用例1
【やりたいこと】
プレイヤーがドアを入口を通過したら、パーティクルを生成する処理。
すり抜けるオブジェクト:プレイヤー
すり抜けられるオブジェクト:ドアにあたる部分に設置された透明なオブジェクト
【スクリプト例】
Public class SampleDooTrigger : MonoBehaviour
{
public GameObject particleEffectPrefab; // パーティクルエフェクトのプレハブ
void OnTriggerEnter(Collider other)
{
// トリガーゾーンに入ったオブジェクトがプレイヤーかどうかを確認
if (other.CompareTag("Player"))
{
// パーティクルエフェクトをプレイヤーの位置で生成
Instantiate(particleEffectPrefab, other.transform.position, Quaternion.identity);
Debug.Log("Player entered the door. Particle effect instantiated.");
}
}
}
使用例2
【やりたいこと】
プレイヤーが警戒ゾーンに立ち入ると、敵がプレイヤーに気付き攻撃をしてくる、という処理の実装。
すり抜けるオブジェクト:プレイヤー
すり抜けられるオブジェクト:警戒ゾーンとして設置された透明なオブジェクト
【スクリプト例】
・透明オブジェクトにアタッチするスクリプト
public class AlertZone : MonoBehaviour
{
public EnemyBehavior enemyScript; // 敵スクリプト
void OnTriggerEnter(Collider other)
{
// トリガーゾーンに入ったオブジェクトがプレイヤーかどうかを確認
if (other.CompareTag("Player"))
{
// 敵にプレイヤーの位置を設定し、攻撃を開始させる
enemyScript.player = other.transform;
enemyScript.AttackPlayer();
Debug.Log("Player entered the alert zone. Enemy will attack.");
}
}
}
・敵スクリプト
public class EnemyBehavior : MonoBehaviour
{
public Transform player;
public void AttackPlayer()
{
if (player != null)
{
// プレイヤーへの攻撃処理
Debug.Log("Enemy attacks the player!");
}
}
}
おわりに
この関数はめちゃくちゃ使うので、自分のためにも整理しておきたかったのです。満足!😊
これだけじゃなくて他にもたくさん備忘録として置いておきたいものがあるので、どんどんnote書いていくつもりです。とにかく書き溜めておきたい!という感じなので、きっちりとした言葉・文法で書くつもりはなく、気軽に書いていこ~という気持ち。
まだまだ勉強中で、間違ってること言ってるかもしれないので(むしろそっちのほうが多いかも)、その時は教えてくださるとめちゃめちゃありがたいです!