Unityの衝突判定の話
衝突難しいよね。
衝突 (Collidion) と検出 (Trigger)
Unityの衝突判定は2つに分かれます。
衝突 (Collision)
物体同士が進入して物理的な影響が発生する場合
検出 (Trigger)
物体同士が進入したことを検出するだけの場合
Colliderの設定
IsTrigger
オンの場合は検出判定のみが行われます。
この部屋に入ったらイベント発生みたいな場合に使われる。
持てるが乗れないアイテムにも使える
Rigidbodyの設定
Rigidbodyなし
物理的な移動をしない (速度を設定できない)
床や壁など動かないものに使用する。
動くものに仕様すると処理が重くなる。
アニメーションで動かしても速度を持たないので、他のものにぶつけても押し出されるor乗り上げるような挙動になります
Rigidbodyあり
物理的な影響を与え、物理的な影響を受ける
物理的なものに使用する
アニメーションで直接動かしても速度を持たないのは同様。Jointなどで速度を持たせることは可能
Rigidbodyあり、IsKinematicオン
物理的な影響を与えるが、物理的な影響を受けない
アニメーションで動く床や持って離すと固定されるアイテムに使用する
※ clusterでは、他人がOwnerのMovableItemや、掴んでいるGrabbableItemはこの設定に変更されます
ColliderとRigidbodyのまとめ
ColliderとRigidbodyの設定で合計6種類ありますが、大きく分けて以下の3タイプになります
検出のみ : コライダーのIsTriggerオン
物理的影響を受けない : RigidbodyなしまたはRigidbodyのIsKinematicオン
物理的影響を受ける : 通常のコライダーで通常のRigidbody
衝突イベント
OnCollideItemTriggerは、UnityのイベントであるOnCollisionEnterやOnTriggerEnterなどで動いています。
OnCollideItemTriggerのTriggerTypeが
Collisionなら衝突した (OnCollisionEnter) と分離した (OnCollisionExit) を受け取ります。
Triggerなら進入を検出した(OnTriggerEnter)と分離を検出した (OnTriggerExit) を受け取ります。
Everythingなら両方受け取ります。
衝突イベントが起きるには、どちらかにRigidbodyがついている必要があります。
Rigidbodyは子のコライダーをまとめて判定を行います。
RigidbodyをつけないOnCollideItemTriggerを作る場合は、そのGameObject自身のコライダーしか判定しないことに注意です。
衝突イベントの表を上記のまとめで作ると以下のようになります。
table: 設定と衝突イベントの関係
\ 検出のみ 物理的影響を受けない 物理的影響を受ける
検出のみ Trigger Trigger Trigger
物理的影響を受けない 省略 Collision Collision
物理的影響を受ける 省略 省略 Collision
補足
a : Rigidbodyなし、IsTriggerオン
b : Rigidbodyあり、IsKinematicオフ、IsTriggerオン
c : Rigidbodyあり、IsKinematicオン、IsTriggerオン
d : Rigidbodyなし、IsTriggerオフ
e : Rigidbodyあり、IsKinematicオフ、IsTriggerオフ
f : Rigidbodyあり、IsKinematicオン、IsTriggerオフ
table: 全パターン
\ a b c d e f
a × Trigger Trigger × Trigger Trigger
b 省略 Trigger Trigger Trigger Trigger Trigger
c 省略 省略 Trigger Trigger Trigger Trigger
d 省略 省略 省略 × Collision Collision
e 省略 省略 省略 省略 Collision Collision
f 省略 省略 省略 省略 省略 Collision
説明すると以下のようになるのですが、直感的には分かりづらいかもしれません。
1. どちらかにRigidbodyが必要
(そもそも衝突判定を始める必要がある)
2. どちらかがTriggerならTrigger
(Triggerは物理的影響を与えないので、相手がどうだろうとTriggerとして判定する)
MeshColliderの凸形状 (Convex)
凸形状でないMeshCollider (非ConvexのMeshCollider) には以下の制限があります。
RigidbodyのIsKinematicをオフにできない
コライダーをIsTriggerにできない
Convexをオンにすると、コライダーの凹みが自動で埋められます
Convexのほうが処理が軽いので、凹みが必要な場合以外はオンにすることをオススメします
CharacterController
キャラクターの移動などに使われるChacterControllerは物理挙動を受けない (IsKinematic) コライダーです。
乗り物やベルトコンベアが難しいのは物理挙動を受けないためです。
RigidbodyのCollision Detection
RigidbodyにはCollision Detectionではすり抜け対策の設定ができます。
Discrete
すり抜け対策なし
Continuous
Rigidbodyのないコライダーに対してすり抜け対策 (連続判定) を行います
IsKinematicがオフの場合のみ設定でき、動作が重めです
Continous Dynamic
Continuousの場合に加え、Continuousの設定をしたRigidbody付きの他のコライダーとの判定でもすり抜け対策を行います
IsKinematicがオフの場合のみ設定でき、動作がとても重いです
Continuous Speculative
雑なすり抜け対策を行います
IsKinematicがオンでも設定できます (というかContinuous設定してると勝手にこれに変更される)
速く移動や回転をする場合、すり抜けたり、逆に当たっていないはずが当たった判定になる場合があります
回転にも対応してるのは実はこれだけなので、回転する細長いものがすり抜けて困るときはこれを設定してください
これらはIsTriggerな判定では行われません
掴んでいるアイテムが衝突しない?
clusterでは、掴んでいるアイテムは元の設定に関わらずIsKinematicがオンに設定されます。
この場合、上のColliderとRigidbodyのまとめでは物理的影響を受けるものが物理的影響を受けないことになります。
これを避けるには、以下のいずれかの方法が考えられます
どちらかをA、つまりIsTriggerにする
衝突が本当に必要なものでないならIsTriggerをオンにすると良いです (物理判定しないので動作も軽くなります)
衝突も必要なら、同じか少し大きめのIsTriggerのコライダーをつけ、Triggerとしての判定を使います (持ってないときにちょうど1回判定させるのが難しくなるかもしれません)
ぶつけられる側をC、つまり物理挙動を受けるようにする
IsKinematicがオフのRigidbodyをつけますaa
ただし、それだと元と大きく挙動が変わってしまうと思うので、そのRigidbodyのConstraintsをすべてオンにして動かなくすると大体は大丈夫だと思います
※この事象は他人がオーナーのアイテムでも同様ですが、オーナー目線ではもとのまま&物理判定はオーナーがやっているのであまり気にしなくても大丈夫です
ワールド制作部