[Unity] Physics衝突判定(RigidbodyとCollider)

どうも、tatsuです!

今回はPhysicsを使って簡単に衝突判定を行う方法について説明しようと思います。

Physicsとは?

PhysicsとはUnityに標準でついている物理エンジンのことで、オブジェクトの物理的な衝突や重力操作を行ってくれるライブラリです。
 
例えばシーンにそのままオブジェクトを配置した段階でゲームを動かしてみても全てのオブジェクトはその場に止まったままですが、プレイヤーにPhysicsを付けると重力に従って下に落ちていきます。
また、地面にもPhysicsを付けることでプレイヤーが地面にあたるとその場に止まります。
 
簡単なゲームではPhysicsを使わなくても当たり判定を実装できますが、複雑な当たり判定を行いたい場合にはPhysicsを使用すると楽に実装できるのでぜひ使ってみてください!

Physicsの種類

今回説明するPhysicsはRigidbodyとColliderです!
基本的にこの2つを知っていれば衝突判定はできます。
さて、これらはそれぞれ何を意味するのでしょうか?

Rigidbody(リジッドボディ)

Rigidbodyはコンポーネントの1つで、オブジェクトにアタッチすることで物理的な操作を行ってくれます。
例えば重力が働いたり、ぶつかった時にある程度跳ね返ったりします。
プレイヤーなど、動くオブジェクトにアタッチすることが多いです。

Collider(コライダー)

Colliderはコンポーネントの1つで、オブジェクトにアタッチすることで衝突器の役割をします。
円・四角などさまざまな形があり、オブジェクトの形に合わせて設定することができます。
動くオブジェクト、地面や壁など動かないオブジェクト両方にアタッチします。

Physicsの使用方法

使用方法は2D/3Dともほぼ同じで、インスペクタの[Add Component]→[Physics(Physics2D)]から選択することができます。
下図ではPhysics2Dを例にしています。

例えば、下図の赤丸(redBall)にはRigidbodyとCircleColliderをアタッチしてあります。
また、下の白い地面(whiteGround)にはBoxColliderをアタッチしてあります。
これを実行すると、Rigidbodyによって重力が効いた赤丸が落っこちていき、互いのColliderがぶつかることで停止します。

どちらかのColliderがアタッチされていないとすり抜けてしまいます。

衝突を検知する

さて、これで衝突自体はできてしまいましたね。
次はスクリプト側で衝突を検知して何か処理を行ってみましょう!
 
とその前に、衝突判定をするためにwhiteGroundについているBoxCollider2Dの[Is Trigger]にチェックしておきましょう。

それではredBallにアタッチするスクリプト、redBallScriptを作成して以下のようにしてください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class redBallScript : MonoBehaviour {

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

	// redBallが他のCollider(ここではwhiteGround)に接触した時に発動する
	void OnTriggerEnter2D(Collider2D coll){
		Debug.Log("衝突!");
	}
}

これで、redBallがwhiteGroundに衝突した際、コンソールに”衝突!”と出るはずです。
どうでしょう?何かおかしいですね。

コンソールに”衝突!”の文字は表示されましたが、redBallがwhiteGroundをすり抜けてしまいました。
そうなんです、実はRigidbody&ColliderとColliderの衝突判定はすり抜けしか行えません
それではどうするかと言いますと、衝突判定後も物理法則を適用するためにwhiteGroundにもRidigBodyをアタッチする必要があります。
また、[Is Trigger]のチェックボックスは戻しておいてください。
スクリプトも以下のように変更してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class redBallScript : MonoBehaviour {

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

	// redBallが他のRigidBody&Colliderのオブジェクト(ここではwhiteGround)に接触した時に発動する
	void OnCollisionEnter2D(Collision2D coll){
		Debug.Log("衝突!");
	}
}

これでどうでしょうか・・・?

…今度はwhiteGroundも一緒に落下してしましました。
 
これはRigidbodyで重力が効いているためです。
whiteGroundのRigidbody2Dの[Body Type]を「Static」にしてください。
これで動かないはずです。どうでしょうか!

うまくいきました!コンソールにも”衝突!”と表示されています!

衝突関数まとめ

最後に衝突判定の関数を紹介したいと思います。
さっきまで使っていたのも入っているので他のと違いを比べてみてください。

OnTrigger系

OnTrigger系は、主に動くオブジェクトが動かないオブジェクトとすり抜け判定をする時に使用します。
どちらかの[Is Trigger]にチェックをすることが条件。
 
OnTriggerEnter

// RigidBody&ColliderのオブジェクトとColliderのオブジェクトが触れた瞬間に起動する
void OnTriggerEnter2D(Collider2D coll){
	Debug.Log("衝突!");
}

OnTriggerStay

// RigidBody&ColliderのオブジェクトとColliderのオブジェクトが触れている間起動する
void OnTriggerStay2D(Collider2D coll){
	Debug.Log("衝突!");
}

OnTriggerExit

// RigidBody&ColliderのオブジェクトとColliderのオブジェクトが離れた瞬間に起動する
void OnTriggerExit2D(Collider2D coll){
	Debug.Log("衝突!");
}

OnCollision系

OnCollision系は衝突判定したあとも物理法則を維持する場合に使用します。
衝突するオブジェクト同士がRigidbodyとColliderを持つことが条件。
 
OnCollisionEnter

// RigidBody&Colliderのオブジェクト同士が触れた瞬間に起動する
void OnCollisionEnter2D(Collision2D coll){
	Debug.Log("衝突!");
}

OnCollisionStay

// RigidBody&Colliderのオブジェクト同士が触れている間起動する
void OnCollisionStay2D(Collision2D coll){
	Debug.Log("衝突!");
}

OnCollisionExit

// RigidBody&Colliderのオブジェクト同士が離れた瞬間に起動する
void OnCollisionExit2D(Collision2D coll){
	Debug.Log("衝突!");
}
注意
今回はPhysics2Dを例に説明してきましたが、各メソッド名は2Dの場合”2D”が最後につきますが、3Dの場合は何もつかないので注意してくださいね。

まとめ

いかがでしたか?
今回はPhysicsをつかった衝突判定の仕方について記事にしてみました!
Physicsは本当に便利な機能なので、ぜひマスターしてくださいね♪
それでは!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です