UnityのOnCollisionとOnTriggerイベントの受け取りを検証する

今まで何となく使っていたOnCollisionとOnTriggerですが、どういう設定をした時にこのイベントが呼ばれているんでしょうか?

個人的にはコライダの設定で

Is Triggerのチェックを入れるとスクリプトから操作し、キャラクターの進入等を検知し、
Is Triggerのチェックを外すと他のコライダを持つ物体と衝突判定をするようになる。

という感じなので、そういった場面で使っています。

Is Triggerのチェックが入っていればOnTrigger系
Is Triggerのチェックが入っていなければOnCollision系

としています。

スポンサーリンク

OnCollisionとOnTriggerの違いを確認する

実際はお互いがどういう設定の時にイベントが呼ばれるか確認してみます。

イベント1

上のように3つのCubeを作りBox Colliderのチェックを入れたCheck、外したNonCheck、CharacterControllerを設定したCharaを作成します。

それぞれにCheck、NonCheck、Charaというタグを作り設定しておきます。

イベント2

上がCheckのBox Collider

イベント3

上がNonCheckのBox Collider

イベント4

上がCharaのCharacterControllerの設定になります。カプセルコライダ風の当たり判定なので適当に設定をします。

それぞれのゲームオブジェクトにColliderCheckという新しいスクリプトを設定して、下記のように記述します。

イベント受け取り関数を記述し、何らかと接触しイベントを受け取ったら、自分自身のタグを表示します。
まずはCheckを動かし、他のオブジェクトと接触させます。

CheckがCharaと接触した時にお互いのOnTriggerEnter関数が呼ばれました。
Checkを検知エリアとするとCharaである主人公側でも同じようにOnTriggerEnterのイベントを受け取っているという事みたいです。

次にNonCheckに接触させます。
CheckをNonCheckに接触させてもどちらのイベントも発生しませんでした。
衝突に使う物体(NonCheck)と検知エリアで使う(Check)では接触判定は不可能という事ですね。

次にCharaを動かし他のオブジェクトに接触させてみます。
Checkはさきほどやったので予想出来た事ですが、どちらもOnTriggerEnterのイベントが発生しました。
一方、NonCheckと接触させても何もイベントが発生しません。

やるまでもないんですが、NonCheckをCheckやCharaに接触させてもすべてのオブジェクトで何もイベントが発生しませんでした。
さてこれで静的な物体のコライダの接触判定が出来た事になります。

そこで実際のゲームで使う際の事を考えます。

大きい岩などを配置する場合、キャラクターと衝突判定をさせたいのでコライダのIs Triggerのチェックは外します。

ですが、今検証したようにIs Triggerのチェックを外した場合、
衝突時に何らかの処理をしたい時にイベントを発生させる事が出来ません。

そこでさきほどのゲームオブジェクトCheckとNonCheckにRigidbodyを取りつけてみます。

イベント5

上のようにUse Gravityのチェックを外して重力を働かせず、Freeze Rotationにチェックを入れて回転させないようにします。

さきほどと同じようにCheckを他のゲームオブジェクトと接触させてみます。
今度はCharaだけでなくNonCheckにもお互いにOnTriggerEnterイベントが発生しました。

次はCharaを他のゲームオブジェクトに接触させます。
Checkと接触させた時はOnTriggerEnterがNonCheckと接触させた時はOnCollisionEnterが発生しました。

実際のゲームで主人公(Chara)が大きい岩(NonCheck)と接触した時にイベントを受け取る事が出来ます。

次にNonCheckを他のゲームオブジェクトに接触させてみます。
これはまたもややる必要はないですが・・・CheckはOnTriggerEnter、CharaはOnCollisionEnterが発生します。

さて次が最後の検証です。RigidbodyのIs Kinematicにチェックを入れるとどうなるんでしょうか?

まずはCheckのRigidbodyのIs Kinematicだけチェックを入れます。
接触させると、CharaはTrigger、NonCheckはTriggerが発生。

次にNonCheckのRigidbodyのIs Kinematicにもチェックを入れて接触させます。
Charaは何も発生しない、CheckはTriggerが発生しました。

接触イベントを表にまとめました

このような検証をしてゆき、表にしてみました。
縦が接触させる側で、横が接触される側。
接触された側で発生するイベントを表記してあります。(接触させる側でも同じイベントが発生していますが・・・)

Check・・・コライダのIs Triggerにチェックを入れたもの
NonCheck・・・コライダのIs Triggerのチェックを外したもの
Chara・・・CharacterControllerを取りつけたもの
Check&NonKine・・・コライダのIs Triggerにチェックを入れ、Rigidbodyを取りつけIs Kinematicのチェックを外したもの
NonCheck&NonKine・・・コライダのIs Triggerのチェックを外し、Rigidbodyを取りつけIs Kinematicのチェックを外したもの
Check&Kine・・・コライダのIs Triggerのチェックを入れ、Rigidbodyを取りつけIs Kinematicのチェックを入れたもの
NonCheck&Kine・・・コライダのIs Triggerのチェックを外し、Rigidbodyを取りつけIs Kinematicのチェックを入れたもの

Check NonCheck Chara Check&NonKine NonCheck&NonKine Check&Kine NonCheck&Kine
Check Trigger Trigger Trigger Trigger Trigger
NonCheck Trigger Trigger
Chara Trigger Trigger Trigger
Check&NonKine Trigger Trigger Trigger Trigger Trigger Trigger Trigger
NonCheck&NonKine Trigger Collision Trigger Collision Trigger Collision
Check&Kine Trigger Trigger Trigger Trigger Trigger Trigger Trigger
NonCheck&Kine Trigger Trigger Collision Trigger

当初のゲームオブジェクト3つだと検証出来ない部分もありましたので最初からRigidbodyを付けIs Kinematicにチェックを入れたり
外した物を用意し、再検証し直しました。

アルファベットばかりで余計わからなくなってますが・・・・(^_^;)

CharacterControllerを取りつけたブロックを手動で動かして検証した結果を載せていましたが、ゲーム内でスクリプトを使ってキャラクターを動かして検証したところ
こちらも相手方も検知出来ない部分があったので修正しました。

主に使うと思われるCharacterControllerで動かすキャラクター(Chara)と他のゲームオブジェクトを判定する場合を考えると相手方を何にするか決める事が出来ます。
検知エリアの場合はCheck、つまりコライダのIs Triggerにチェックを入れたものを使えばいいことになります。

CharacterControllerで動かすキャラクターの場合はCollisionはこちらも相手も検知出来ず、Triggerでは相手方のIs Triggerにチェックが入っている時だけOnTrigger系で検知出来ます。
CharacterControllerのキャラクターの場合はOnControllerColliderHitという関数で相手方を検知する事が出来るのでこの関数を使用するといいと思います。

Rigidbodyとコライダを使ってキャラクターを動かす方法は

キャラ操作をCharacterControllerからRigidbody+コライダに変更する
Unityでキャラクターを操作する時CharacterControllerを使ってきましたが、物理的な影響を得る為にRigidbody+CapsuleColliderでキャラクターの移動、ジャンプ、坂や段差を登れるようにしてみます。

の記事で取り扱っていますが、

キャラクターはIs Triggerのチェックを外し、RigidbodyのIs Kinematicのチェックを外したNonCheck&NonKinemaになります。

Rigidbody+コライダでキャラクターを動かす時はTrigger、Collisionの検知も出来るので非常に便利です。