Proximityの謎を追え!
VRChatの2023.4.2 Build 1388にて、VRCPickupの掴み判定とUdonのインタラクト判定が正しく機能するようになり、それに合わせてVRCPickupの公式ドキュメントにもProximityについて追記されました。
INDEXコントローラーを使っている身としては、掴み判定は結構センシティブ(ダブルミーニング)な話なので、この機会にドキュメントを読み解き、図解しておこうと思います。
では見ていきましょう。
掴み判定/インタラクト判定の前知識
VRCPickupの掴み(Pickup)判定とUdonのインタラクト(Interact)判定は同質で、そのためどちらにもProximity設定もあれば、Interaction Text(判定が出たときに表示されるTooltip)も設定できます。
という事で、以降はまとめてインタラクト判定と呼称します。
この判定基準はデスクトップモードとVRモードによって別物になっているので、個別に見ていきましょう。
なお、距離計算に出てくる値は全てメートル単位です。
(余談)
ちなみに、いわゆる"Sit判定"は、VRCStationに(Interactイベントを含んだ)Udonを付けずに設置すると、VRChatクライアント上でVRCStation自身が「Sit」という名前(Interaction Text)でインタラクト判定を生成するものです。更にコライダーも付いていない場合は、デフォルトサイズのBoxコライダーも追加されます。なんと迷惑な
アバター椅子もこの仕様を使っています。
デスクトップ/スマホモード
デスクトップモードでは手が動かせないので、判定基準はビューポイントから視線方向に真っ直ぐ伸びた線上です。
インタラクト判定は、まずこの線とインタラクト対象のコライダーが接触するかを判定し、接触していたらビューポイントから接触面までの相対距離を取得します。相対距離がProximityの値以下なら、VRChatはインタラクト判定を発生させます。
なお、デスクトップモードでは腕が伸ばせないので、腕が有るものとしてアバターの腕の長さ(推定値)分のオフセットがProximityに加算されて判定されます。
このため、Proximityを0にしていても、オフセット分の相対距離内までは接触判定が発生します。
VRモード
VRモードではご存じ、右手と左手両方に判定基準があり、インタラクト判定がある程度以上遠くにある場合、それぞれの手から真っ直ぐ伸びた線上に判定基準があります。
(メニューを出した時に出るレーザーポインターと同じ線上なので、遠くに有るものを掴むときの目安になります)
インタラクト判定は、まずこの線とインタラクト対象のコライダーが接触するかを判定し、接触していたら手から接触面までの相対距離を取得します。相対距離がProximityの値以下なら、VRChatはインタラクト判定を発生させます。
インタラクト対象が手の近くにある時は、接触判定は"線"ではなく"球"による判定になります。これは直感的に掴みやすくするための工夫で、相対距離が(0.4 × アバタースケール比)以下の時にこの判定に切り替わります。
インタラクト判定は、まずこの球とインタラクト対象のコライダーが接触するかを判定し、接触していたら手から接触面までの相対距離を取得します。相対距離がProximityの値以下なら、VRChatはインタラクト判定を発生させます。
ちなみに、Proximityが0だとどうなるかというと、手がインタラクト対象コライダーの"内側"に埋まったときに初めてインタラクト判定が発生するようになります。
カードみたいな非常に薄いコライダーのオブジェクトなのにProximityが極小値だと、めちゃくちゃ掴みづらくなる…という事です。とりあえず0.2以上くらいは入れておく方が安牌と思います。