[Unity] Physics.OverlapCapsuleの使い方

2021-09-06更新: 対象のGameObjectのrotationと、CapsuleColliderのdirectionを考慮するように大きく修正した。

Capsule and Cube Collider

上記のようにCapsulColliderと重なった2つのColliderを取得するには、Physics.OverlapCapsuleを使用する。このメソッドは、カプセルの位置と大きさを受け取り、そのカプセルと重なっているすべてのColliderを返す。

Kinematic Rigidbody Trigger Collierを構成して、OnTriggerEnterメッセージを処理することでもCollidersを取得できるが、このメソッドのほうが簡単だし、便利な応用方法もある。

Physics.OverlapCapsuleの必須の引数のみのシグネチャを以下に示す。

次の図の左側にこれらの引数を示す。point0point1はそれぞれどちらかの半球の中心を表す。radiusには半径が入る。CapsuleColliderの仕様は右側に示すように、中心、高さ、半径からなっている。そのため変換が必要である。

以下は、右のCapsuleColliderに対応するpoint0point1の計算方法である。 この計算には、CapsuleColliderのdirectionを考慮する必要がある。directionは0, 1, 2のいずれかであり、それぞれX軸、Y軸、Z軸に対応する。

このlocalPoint0localPoint1をワールド空間に変換するとpoint0pint1になる。

Physics.OverapCapsuleの半径もワールド空間なので、CapsuleColliderの半径をワールド空間に変換する必要があるが、少し面倒である。GameObjectがdirectionの垂直面で楕円の場合は、半径を長径側に拡大する必要がある。以下はその実装である。TransformVectorの返すベクトルの要素はマイナスになることがあることに注意してほしい。

最後に、これまでに求めた値を使ってPhysics.OverlapCapsuleを呼び出す。

当然のことながら、返ってくるColliderにはCapsuleColliderも含まれることに注意してほしい。避けたければ、あらかじめCapsuleColliderを無効化しておくとよい。

Physics.OverlapCapsuleを用いると、対象のCapsuleCollderよりもサイズを小さくして、触れているだけのColliderを除外するとか、サイズを大きくして接触しそうなColliderを取得するといったことが自在に行える。

ところで、Physics.OverlapCapsuleは呼ぶたびに配列をアロケートして結果を返すので、毎フレーム呼ぶ場合には大量にゴミが出てしまう。その場合には、Physics.OverlapCapsuleNonAllocで事前にアロケートした配列で結果を受け取る。使用例を以下に示す。

重なりを5つまで検出する場合は、5要素のColliderの配列をUpdateの外で作っておく。それをPhysics.OverlapCapsuleNonAllocに渡して実行すると、_resultに検出したColliderが格納されて、その数が返値として返る。

コメントを残す

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