Edited at

UnityのRigidbodyとColliderで衝突判定

More than 1 year has passed since last update.


動画とスライド

勉強会の記事がブログにあります。(日本法人閉鎖により消滅した模様)

http://www.engineyard.co.jp/blog/2014/shimokita-unity-rigidbody/


サンプルシーン

Step1_unity_-_RigidbodyAndCollision_-_PC__Mac___Linux_Standalone.jpg

https://dl.dropboxusercontent.com/u/6626376/Unity/RigidbodyAndCollision.zip


Rigidbodyでできること


  • 重力、加速度を使った処理

  • 衝突した物体を動かす、衝突された物体の動きに作用する

  • 衝突発生時に任意の処理を実行する


自然落下

Sampleシーンを開く。下記のオブジェクトにAdd ComponentをクリックしてPhysics > Rigidbodyを設定。

Step1_unity_-_RigidbodyAndCollision_-_PC__Mac___Linux_Standalone.jpg


設定項目の意味

項目
意味

Mass
重さ。単位はキログラム

Drag
空気抵抗

Angular Drag
回転に対する空気抵抗

Use Gravity
重力を使う

Is Kinematic
物理演算を無効にする

Interpolate
フレーム間の補間

Collision Detection
衝突検知モード。高速で動く物体には変更

Constraits
移動や回転を軸ごとに無効にする


地面が落ちてしまう場合

Rigidbodyは物理演算で動作させるオブジェクトに設定する。壁や床はRigidbodyを付ける必要はない。


地面をすり抜けてしまう場合

Untitled.gif

アセットや変換したモデルがすり抜けてしまう場合はオブジェクトにColliderが設定されていないのが原因。重力で落下した物体が地面に着地するにはそれぞれに下記のコンポーネントが必要になる。

CubeやSphereなどのプリミティブには最初からColliderが付いている。


  • 落下する物体


    • 物体の形に応じたCollider

    • 重力が設定されたRigidbody



  • 受け止める地面


    • 地面の形に応じたCollider



すり抜けて落下していく物体にはPhysics > BoxColliderなどのコンポーネントを設定する。入れ子になっているオブジェクトの場合はそれぞれの子オブジェクトに指定するか、親オブジェクトに指定する。子オブジェクトにColliderを設定した場合は合成した形で親オブジェクトに適用される。

コライダーはシーンでオブジェクトをクリックするとワイヤフレームで表示される。

例

球体にあえて四角形の判定をつけたりすることも出来る。

Step1_unity_-_RigidbodyAndCollision_-_PC__Mac___Linux_Standalone.jpg

レンダラーを無効にすれば表示されないが、判定はあるということも可能。


力を加える

Rigidbodyが設定されたオブジェクトにはスクリプトから力(Force)と回転(Torque)を加えることができる。

メソッド
効果

AddForce
力を加える

AddRelativeForce
相対座標で力を加える

AddTorque
回転を加える

AddRelativeTorque
回転を加える

力を加える時にはForceMode指定することでさらに挙動が変わる。

モード
効果

Force
質量が反映する、連続的な力を加える

Acceleration
質量を考慮しない、連続的な加速を加える

Impulse
質量が反映する、瞬間的な力を加える

VelocityChange
質量を考慮しない、連続的な速度の変化を加える


ControlScript.js

#pragma strict

function Update () {

var speed = 100;

if (Input.GetKeyDown(KeyCode.LeftArrow)) {
rigidbody.AddForce(Vector3.left * speed, ForceMode.Force);
}

if (Input.GetKeyDown(KeyCode.RightArrow)) {
rigidbody.AddForce(Vector3.right * speed, ForceMode.Force);
}

}


Forcemode.Forceの場合は力を加えて揺らすようなイメージ。

Untitled.gif

Forcemode.VelocityChangeは操作に応じてひとまず動きに反映されるイメージ。

Untitled.gif

ForceModeやspeedを調整してみるとさまざまな動きをする。力を加えると意図しない回転をしてしまうことも多い。プレイヤーなど操作を反映させる場合は不都合な場合も。不都合がな場合はConstraitsで回転を封じる。


上下左右に動く例

#pragma strict

function Update () {

var speed = 3;

if (Input.GetKeyDown(KeyCode.LeftArrow)) {
rigidbody.AddForce(Vector3.left * speed, ForceMode.VelocityChange);
}

if (Input.GetKeyDown(KeyCode.RightArrow)) {
rigidbody.AddForce(Vector3.right * speed, ForceMode.VelocityChange);
}

if (Input.GetKeyDown(KeyCode.UpArrow)) {
rigidbody.AddForce(Vector3.forward * speed, ForceMode.VelocityChange);
}

if (Input.GetKeyDown(KeyCode.DownArrow)) {
rigidbody.AddForce(Vector3.back * speed, ForceMode.VelocityChange);
}

}



衝突時に処理を行う

衝突が発生すると状況に応じて次のコールバックが実行される。それぞれの処理内で衝突の状況に応じて任意の処理を行うことで動きを作る。この際の処理はRigidbodyがメッセージ機能を使い、相手のオブジェクトと自分のオブジェクトの対応する処理を呼び出している。

コールバック
動作

OnCollisionEnter
他のColliderやRigidbodyオブジェクトに触れた時に呼び出される

OnCollisionExit
他のColliderやRigidbodyオブジェクトに離れた時に呼び出される

OnCollisionStay
他のColliderやRigidbodyオブジェクトに触れ続けている時に呼び出される


衝突時に自分を消去

#pragma strict

function OnCollisionEnter(other:Collision) {

Destroy(gameObject);

}


Untitled.gif


衝突時に相手を削除

#pragma strict

function OnCollisionEnter(other:Collision) {

Destroy(other.gameObject);

}


Untitled.gif


衝突対象の判別

衝突対象に無差別に処理を行うのは得策ではないので、衝突対象を判別した上で処理を行う必要がある。そのためにはタグを使った判定を行うのがよい。タグはインスペクタから設定可能。デフォルトのタグの他に、任意のタグを追加可能。

Step3_unity_-_RigidbodyAndCollision_-_PC__Mac___Linux_Standalone_と_Inbox_-_yandod_gmail_com_-_Gmail.jpg

とりあえずプレイヤーと思われるプレゼントにPlayerを設定、衝突されるボールや箱側にスクリプトを付け、 プレイヤーがぶつかってきた時 に処理を行うようにする。


ボールなどに設定するスクリプト

#pragma strict

function OnCollisionEnter(other:Collision) {

if (other.gameObject.CompareTag('Player')) {
//move to this object to above.
gameObject.transform.position = Vector3.up * 5;
}
}


Untitled.gif


衝突はさせずに処理を行う

ゴールエリアや風が吹くエリア、など一定の範囲にいると処理を行うという場合にはTriggerを使う。具体的にはColliderIsTriggerをOnにすると衝突はしないが専用のコールバックが呼び出される。

Step4_unity_-_RigidbodyAndCollision_-_PC__Mac___Linux_Standalone.jpg

コールバック
動作

OnTriggerEnter
他のColliderやRigidbodyオブジェクトに触れた時に呼び出される

OnTriggerExit
他のColliderやRigidbodyオブジェクトに離れた時に呼び出される

OnTriggerStay
他のColliderやRigidbodyオブジェクトに触れ続けている時に呼び出される


触れてきたオブジェクトを右へ飛ばす

#pragma strict

function OnTriggerEnter(collider:Collider) {
if (collider.gameObject.CompareTag('Player')) {
return;
}
collider.gameObject.rigidbody.AddForce(
Vector3.right * 30,
ForceMode.Impulse
);

}


Untitled.gif


参考資料