16. 相互作用
16.1 AB間の相互作用を決める条件
Unityにおける応答タイプは、「衝突(Hit)」「重複(Trigger)」の2種類があります。
UnityにおいてAB間の相互作用を決める条件と、さらに応答タイプ「衝突」または応答タイプ「重複」が発生する条件をまとめました。RigidbodyコンポーネントとColliderコンポーネントの有無は、AB間の応答タイプの相関性から相互作用が発生する前提条件になっており、前提条件が揃ったゲームオブジェクトに対して「衝突」させるのか、「重複」させるのかを決めていきます。
1. AB間の相関性から相互作用(AB間の「衝突」・「重複」)が決まる条件
a. RigidbodyコンポーネントをAかBのどちらか、またはAB両方に追加すること
b. Colliderコンポーネントを両方に追加すること
2. 応答タイプ「衝突」が発生する条件
a. ColliderコンポーネントのIsTriggerがAB両方ともにOFFであること
「重複」はOnCollisionEnter/Exit関数で検出することができます。OnCollision関数あるCollisionクラスの引数collisonから相互作用の情報を受け取ることができます。
3. 応答タイプ「重複」が発生する条件
a. ColliderコンポーネントのIsTriggerが片方がONまたは両方がONであること
「衝突」はOnTriggerEnter/Exitで検出することができます。OnCollision関数あるCollisionクラスの引数collisonから相互作用の情報を受け取ることができます。
AB間の応答タイプの相関性の条件を揃えた上で、「衝突」または「重複」が発生する条件をまとめたマトリックス表は以下になります。
RigidbodyコンポーネントとColliderコンポーネントの有無についてマトリックス表でまとめた資料をネットでみかけましたが、情報が冗長になってしまうので、相互作用の条件は前提条件として分け、「衝突」と「重複」の違いに焦点を当てマトリックス表を作成したほうがよいと思います。
|
BゲームオブジェクトのCollisionコンポーネントのIsTrigger |
ON |
OFF |
AゲームオブジェクトのColliderコンポーネントのIsTrigger |
ON |
「重複」 |
「重複」 |
OFF |
「重複」 |
「衝突」 |
SphereAの子にSphereA'ゲームオブジェクトを追加します。SphereA'ゲームオブジェクトにはスクリプトを外しておきます。
16.2 コライダーの「衝突」を発生させる
それでは「衝突」を発生させます。シーン上に二つのSphereゲームオブジェクトを置いて、赤いSphereをSphereA、青いSphereをSphereBとします。SphereにはSphere Colliderコンポーネントが追加されていることと、ColliderコンポーネントのIsTriggerがデフォルトでOFFになっていることを確認します。SphereAゲームオブジェクトにRigidbodyコンポーネントを追加します。
Physic Materialを作成します。名前をBounceにします。
SphereAとSphereBのスクリプトを用意します。
SphereAゲームオブジェクト用のObjectAコンポーネントを用意します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectA : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
Debug.Log("Object Collision A: " + collision.gameObject.name);
}
}
SphereBゲームオブジェクト用のObjectBコンポーネントを用意します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectB : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
Debug.Log("Object Collision B: " + collision.gameObject.name);
}
}
ObjectAコンポーネントとObjectBコンポーネントをそれぞれのゲームオブジェクトに追加して、先ほど作成したBounce Physic materialを追加します。
SphereAのインスペクタです。
SphereBのインスペクタです。
playを実行して、SphereAゲームオブジェクトをマウスで選択して、SphereBゲームオブジェクトに向かって移動させます。
SphereAからSphereBへの衝突のイベントについて、両方が「衝突」を検知していることがわかります。
次に、SphereAの子のゲームオブジェクトSphereA'とSphereBとの「衝突」について考えます。
SphereA'を追加したSphereAの位置を上に移動させ、SphereA'とSphereBをぶつけたときの相互作用を確認します。
SphereA'にはRigidbodyコンポーネントは外し、Sphere ColliderコンポーネントのIsTriggerはOFFにします。
- SphereA(親)
- Transformコンポーネント
- Sphere(MeshFilter)コンポーネント
- Mesh Rendererコンポーネント
- Sphere Colliderコンポーネント
- Rigidbodyコンポーネント
- ObjectAコンポーネント
- Sphere A'(子)
- Transformコンポーネント
- Sphere(MeshFilter)コンポーネント
- Mesh Rendererコンポーネント
- Sphere Colliderコンポーネント
- SphereB
- Transformコンポーネント
- Sphere(MeshFilter)コンポーネント
- Mesh Rendererコンポーネント
- Sphere Colliderコンポーネント
- Rigidbodyコンポーネント
- ObjectBコンポーネント
Playを実行して、SphereA'がSphereBと「衝突」したときに、親となるSphereAのObjectAコンポーネントにSphereBの名前が表示されていることがわかります。
ちなみにSphereA'にRigidbodyコンポーネントを追加すると、SphereA'がSphereBと衝突したときは、親となるSphereAが子のSphereA'の「衝突」を検知しなくなり、SphereBはSphereA'の「衝突」を検知するようになります。
相手との「衝突」をレイヤーによって有効にするかを判定することができるRaycasts Hit Triggers機能を確認します。
SphereAの親子関係のSphereA'を削除して、シーン上にSphereAとSphereBについて、SphereBを上に、SphereAを下に設置します。
Layerに新しく値を追加します。
インスペクタのLayerをクリックしてAdd Layer...をクリックします。
User Layer 7 に新しくSphereを登録します。
さらにUser Layer 8 に新しくPlaneを登録します。
SphereAのインスペクタです。LayerはDefalutのままにします。
SphereBのインスペクタです。LayerはSphereに変更します。
Planeのインスペクタです。LayerはPlaneに変更します。
次にEdit > Project Settings >PhysicsでRaycasts Hit Triggersを表示してDefaultとSphereの交差点のチェックを外します。
playを実行すると、LayerがSphereのSphereAが落下すると、LayerがDefaultのSphereBは無視して、Planeと衝突して着地していることが確認できます。
16.3 コライダーの「重複」を発生させる
「衝突」で使用したシーン上の二つのSphereゲームオブジェクトを使います。このままですとPlayを実行したときにRigidbodyコンポーネントの働きでPlaneの下にすり抜けてしまい、SphereBとの相互作用が確認できなくなってしまうためSphereAはSphereBの上に移動させておきます。SphereAにあるBox ColliderコンポーネントのIsTriggerをONにします。SphereAゲームオブジェクトにRigidbodyコンポーネントが追加されていることを確認します。
ObjectAとObjectBのスクリプトを書き換えます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectA : MonoBehaviour
{
void OnTriggerEnter(Collision collision)
{
Debug.Log("Object Trigger A: " + collision.gameObject.name);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectB : MonoBehaviour
{
void OnTriggerEnter(Collision collision)
{
Debug.Log("Object Trigger B: " + collision.gameObject.name);
}
}
SphereAのインスペクタです。
SphereBのインスペクタです。
playを実行すると、SphereAゲームオブジェクトが落下します。
SphereAからSphereBへの「重複」のイベントについて、両方が「重複」の相互作用が働いていることが確認できます。Planeに対しても「重複」の相互作用が働きました。
それからスクリプト側で以下のようにOnTriggerEnterとOnCollisionEnterの両方を記述しても、インスペクタで設定した「衝突」または「重複」のどちらかの条件に従ってOnTriggerEnterとOnCollisionEnterのどちらかが呼ばれます。両方が呼ばれることはありません。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectA : MonoBehaviour
{
void OnTriggerEnter(Collision collision)
{
Debug.Log("Object Trigger A: " + collision.gameObject.name);
}
void OnCollisionEnter(Collision collision)
{
Debug.Log("Object Collision A: " + collision.gameObject.name);
}
}
次に、SphereAの子のゲームオブジェクトSphereA'とSphereBとの「重複」について考えます。
SphereA'にはRigidbodyコンポーネントは外し、Sphere ColliderコンポーネントのIsTriggerはONにします。
- SphereA(親)
- Transformコンポーネント
- Sphere(MeshFilter)コンポーネント
- Mesh Rendererコンポーネント
- Sphere Colliderコンポーネント
- Rigidbodyコンポーネント
- ObjectAコンポーネント
- Sphere A'(子)
- Transformコンポーネント
- Sphere(MeshFilter)コンポーネント
- Mesh Rendererコンポーネント
- Sphere Colliderコンポーネント
- SphereB
- Transformコンポーネント
- Sphere(MeshFilter)コンポーネント
- Mesh Rendererコンポーネント
- Sphere Colliderコンポーネント
- Rigidbodyコンポーネント
- ObjectBコンポーネント
Playを実行して、SphereA'がSphereBと「重複」したときに、親となるSphereAのObjectAコンポーネントにSphereBの名前が表示されていることがわかります。
ちなみにSphereA'にRigidbodyコンポーネントを追加すると、SphereA'がSphereBと「重複」したときは、親となるSphereAが子のSphereA'の「重複」を検知しなくなり、SphereBはSphereA'の「重複」を検知するようになります。
16.4 AB間の応答タイプの相関性による相互作用から得られる情報
「重複」や「重複」を発生させる際に作成したスクリプトでは、相手のゲームオブジェクトの名前を取得して表示させていましたが、他にも取得できる情報があります。この情報はUnityのドキュメントにも記載されています。
- 「衝突」時のUnity Collisionクラスから受け取ることができる相互作用の情報
- Collisionで取得できる情報
- collider ヒットした相手のCollider情報
- contactsCount 物理エンジンによる生成された衝突情報
- contacts 物理エンジンによって生成された接触点
- gameObject ヒットした相手のGameObject情報
- impulse 衝突を解消するために互いの接触に適用されるインパルス
- relativeVelocity 衝突した2つのオブジェクトの相対速度
- rigidbody ヒットした相手のRigidbody情報
- transform ヒットした相手のTransform情報
- 「重複」時のUnity Colliderクラスから受け取ることができる相互作用の情報
- Colliderで取得できる情報
- gameObject 重複した相手のGameObject情報
- tag GameObjectのタグ
- transform 重複した相手のTraosnfom情報
- name GameObjectのオブジェクト名
🔗 参考リンク
Unity Documentation
Collision
🔗 参考リンク
Unity Documentation
Collider