Programming in VRChat

VRChat でのプログラミングについて調べたことの書き溜め

ProtectCameraFromWallClip

概要

あるオブジェクトを一定間隔で追跡(フォロー)するカメラにおいて、 オブジェクトとカメラの間に障害物が入らないように、 カメラとオブジェクトとの距離を一時的に縮めるカメラ位置制御をおこなうスクリプト

(Unity Standard Asset / Cameras)

機能

基礎的な構成と動作

  • ProtectCameraFromWallClip スクリプトが Add されているオブジェクトの子孫から Camera が探される(直接の子である必要はない)
    • スクリプトが Add されているオブジェクトは、Standard Asset のドキュメントにおいて Camera Rig と呼ばれている)
  • Camera の親が配置位置の基準となるオブジェクト
    • 以降、このオブジェクトを Pivot と呼ぶ
    • このオブジェクトを視界ででとらえるように Camera の位置制御が行われる
    • (いわゆるフォローするオブジェクト。ソース中では target とも呼ばれる。)
  • Camera は Pivot のローカル座標において、z軸上のマイナス領域に常に配置される。
    • つまり典型的な使い方は「Pivot が z軸のプラスに進むのを後ろから見る」という状況である。
  • Pivot から見た Camera の初期位置の距離が制御の基準距離になる
    • ソース中では original distance
  • Pivot と Camera の間に障害物が何もなければ、スクリプトは Camera を Pivot の後方、基準距離に配置しようとする
  • Pivot と Camera の間に障害物がある場合、Pivot に最も近い障害物の距離に Camera を配置しようとする。

障害物探索の詳細

  • 障害物の探索には、利用者が指定する半径の球が使われる
  • 基本的な障害物探索領域は、Pivot の前方(Pivot のローカル座標z軸プラス領域)の球半径の位置から、後方 Camera の初期位置距離までを、この球が掃く(Capsul 形状の)領域である。
  • Pivot の前方球半径の位置においた球(つまりPivotの鼻先に置いた球)に既に障害物がある場合には、探索領域は一時的に狭まり、線(Ray)になる。
  • 障害物と認識されるオブジェクトは以下の条件を満たすものに限られる。(逆に言えばいずれかを満たさないようにすれば無視される)
    • レイヤーが Ignore Raycast ではない
    • タグが指定された値ではない
    • Rigidbody がアタッチされている
    • コライダーが Is Trigger ではない

Camera 移動の詳細

  • Camera の配置する場所へは瞬間的な移動ではなく、指定した移動時間をかけて徐々に移動する。
    • よって、Camera 視界において Pivot が一時的に障害物にさえぎられることが起こりうる
  • 最も Pivot に近い障害物の位置に Camera は移動しようとするが、Pivot に近づきてしまうと Pivot 全体を写すことが出来なくなってしまう (通常のゲームであればプレイヤーキャラクターが画面いっぱいに拡大されるまで近づいてしまうとゲームにならない)。 これを避けるために最近接距離が設定できる。Camera は Pivot にこれ以上近づくことは無い。

設定値

  • Clip Move Time
    • Camera が障害物を超えて Pivot に向かって動くまでの移動時間
  • Return Time
    • Camera が基準距離に戻るまでの移動時間
  • Sphere Cast Radius
    • 障害物探索の球の半径
  • Visualize In Editor
    • Unity エディタ上でデバッグ用の表示を有効にする
  • Closest Distance
    • Camera がそれ以上 Pivot に寄らないようにする距離
  • Dont Clip Tag
    • 障害物探索の際に、障害物とみなさないオブジェクトに付けたタグを指定する

VRChat での活用

本来はカメラを移動するためのスクリプトだが内部に含まれるレイキャストを流用して、オブジェクトを移動するのに使える。 つまり、ある場所(Pivotをここに置く)からある方向(Pivotのローカル座標マイナスz方向)へ向かって、一番手前にあるオブジェクト(障害物)の位置へオブジェクト(Camera)を移動させることが出来る。

実装疑問点

初期の OverlapSphere 検査で障害物が見つかった時の RaycastAll 探索開始位置が不可解。 Camera 側に寄せるべきな気がするが、初期検査からプラスしているので向こう側になっているはず。