Contact SenderのHeightが0のとき、ContactEnterInfo.contactPointがSenderではなくアバターのルート位置を返す
【概要】
ワールドのBOXタイプのVRCContactReceiverでOnContactEnterを受け取ったとき、ContactEnterInfo.contactPointが接触位置を返さない場合があります。
条件はContact Sender側のコライダーのHeightが0(スフィア形状)であること。このときcontactPointはSenderの位置を無視し、アバターのルート位置(VRCPlayerApi.GetPosition())をReceiverの形状内にクランプした値を返します。
Heightが0以外のSender(カプセル形状)では、contactPointは正しく接触位置を返します。
【環境】
正式版[1862]、ベータ版[1882]共に発生します。
【再現手順】
再現用のワールドをアップロードしました。こちらでご確認ください。
このワールドにはVRCContactReceiver(Shape: Box、Content Types: Avatar、Collision Tags: Head HandL HandR FootL FootR)を設置した鏡を置いてあり、OnContactEnterで触れた場所を中心に鏡にヒビがはいり、以下のログを出力します。
Debug.Log($"[ContactPointCheck] contactPoint={info.contactPoint} " +
$"senderPos={sender.position} " +
$"AvatarRoot={player.GetPosition()} tags={tags}");
※tagsはHead / HandL / HandR / FootL / FootRのいずれかが出ます。
【手順】
アバターのAvatar Descriptor → Colliders で、Hand LのみHeightを0に設定してアップロードする(Hand Rは既定のまま)
上記ワールドに入り、左右それぞれの手で鏡に触れる
ログのcontactPointをsenderPosおよびAvatarRootと比較する
頭・足については、既定のAvatar DescriptorがそのままHeight=0のため、設定を変更せずに再現します。
【期待される結果】
左右どちらの手でも、contactPointが実際の接触位置を返す。
【実際の結果】
Hand R(Height ≠ 0)— 正常。senderPosに追従している
[ContactPointCheck] contactPoint=(-1.92, 1.18, -0.03) senderPos=(-1.92, 1.17, -0.09) AvatarRoot=(-2.04, -0.01, -0.46) tags=HandR
[ContactPointCheck] contactPoint=(-1.88, 1.09, -0.03) senderPos=(-1.88, 1.08, -0.09) AvatarRoot=(-2.03, -0.01, -0.45) tags=HandR
Hand L(Height = 0)— 異常。AvatarRootに一致している
[ContactPointCheck] contactPoint=(-2.02, 0.00, -0.03) senderPos=(-2.25, 1.25, -0.07) AvatarRoot=(-2.02, -0.01, -0.36) tags=HandL
[ContactPointCheck] contactPoint=(-2.00, 0.00, -0.03) senderPos=(-2.25, 1.13, -0.08) AvatarRoot=(-2.00, -0.01, -0.39) tags=HandL
XがAvatarRootと完全に一致しています。YもAvatarRootの値(-0.01)がReceiverの下端(0.00)へクランプされた値です。ZはAvatarRoot(-0.36 / -0.39)ではなくReceiverの面(±0.03)にクランプされており、ルート位置をReceiverの形状内へ収めた結果であることが分かります。
【備考】
既定設定のHead / Foot(いずれもHeight = 0)も同様に異常
[ContactPointCheck] contactPoint=(-1.51, 0.00, 0.03) senderPos=(-1.51, 1.17, 0.07) AvatarRoot=(-1.51, -0.01, 0.07) tags=Head
[ContactPointCheck] contactPoint=(-1.51, 0.00, 0.03) senderPos=(-1.59, 0.05, -0.06) AvatarRoot=(-1.51, -0.01, 0.07) tags=FootL
[ContactPointCheck] contactPoint=(-1.51, 0.00, 0.03) senderPos=(-1.47, 0.12, 0.07) AvatarRoot=(-1.51, -0.01, 0.07) tags=FootR
この3行は同じ瞬間に3つのSenderが触れたもので、Head・FootL・FootRがすべて同一の座標を返しています。
【影響】
既定のAvatar DescriptorではHeadとFootのHeightが0のため、設定を変更していない多くのアバターがこの条件に該当します
体の部位が触れた位置に応じて演出を出すワールドギミックにおいて、既定のアバターでは頭・足の接触位置が取得できません。
【参考動画】