SabaProps

SabaProps Stage Cam

ワールド側から特定のプレイヤーの部位を追い、一定距離と固定アングルを保つ Udon カメラリグです。
ステージのある種のワールドで、演者を追い続けるカメラを置くことを想定しています。

  • 追える部位は顔・首・胸・体・左右の手・左右の足の 8 種類
  • アングルは被写体の体の向きを基準にも、ワールド固定にも取れます
  • Pickup で掴んで構図を直すと、その位置が新しい定常アングルになります
  • 被写体の周囲を自動で回り込むクレーン風のカメラワーク
  • アバターの身長差を吸収する自動フレーミング

0.2.0 まではローカル専用です。各クライアントが自分の見たい対象を自分で追います。
全員で同じ画を見る運用は 0.3.0 で入れます(ロードマップ)。

Stage Camera World Sample をUnityで表示した画面

同梱Sample SceneをUnity 2022.3で表示した画面です。ステージ、2台のカメラ、2枚のWorld Screenを確認できます。

Stage Cam の実行時構成図

追従対象と Pickup 操作を Stage Cam Rig が受け取り、Camera の RenderTexture を経由して World Screen に表示します。0.2.0 までは表示は各クライアントのローカルです。


導入

VCC でこのパッケージを追加すると、依存する VRChat Worlds SDK も一緒に解決されます。

使い方

デモシーン

Tools > SabaProps > Stage Cam > Create Sample Scene で、ステージ・2 枚のスクリーン・
2 台のカメラ・VRChat の Spawn を生成します。保存先は
Assets/SabaProps/StageCam/Samples/StageCamDemo.unity です。
RenderTexture とマテリアルも同じフォルダに生成します。

  • Face Cam: 顔を追従し、身長に合わせて距離を調整します。
  • Crane Cam: 胸を追従し、20 秒周期で回り込みます。カメラ形状の本体を Pickup して基準の構図を補正できます。

どちらも起動時にローカルプレイヤーを対象にします。画面の向きとシーン構成は Editor で
確認できますが、追従と Pickup 補正の動作確認には VRChat の Build & Test を使用してください。
ClientSim は PostLateUpdate を呼ばないため、Play だけでは追従しません。

生成し直すと同名のシーンを上書きします。編集を残す場合は別名で保存してください。

完成済みの VRChat World サンプルは UPM/VCC の Package Manager で本パッケージを選択し、
Samples > Stage Camera World > Import から Assets に取り込めます。取り込み後は
Assets/SabaProps/StageCam/Samples/StageCamDemo.unity を開いてください。シーン、RenderTexture、
マテリアル、Udon のシリアライズ済みプログラムをパッケージに同梱しているため、生成メニューを
先に実行する必要はありません。World SDK の VRCSceneDescriptor と Spawn もシーンに含まれます。

手動で配置

GameObject > SabaProps > Stage Camera Rig で、カメラと Collider 付きのリグを配置できます。
個別に構成する場合は以下の手順を使用します。

  1. 空の GameObject に SabaProps/Stage Cam Rig を追加します
  2. その子に Camera を置き、Target Texture に RenderTexture を割り当てます
  3. RenderTexture を貼ったマテリアルで、ワールドにスクリーンを置きます
  4. Target Local Player On Start を入れるか、リグに Collider を付けて触れるようにします

リグに触れると、触れた人が被写体になります。_TargetLocalPlayer / _TargetNearestPlayer /
_ClearTarget を他の Udon から呼んでも指定できます。

Pickup で構図を直したい場合は、リグ本体に SDK3 の VRCPickup と Rigidbody を追加してください。
掴んでいる間はスクリプトが Transform を手放し、離した位置と向きがそのまま新しい定常アングルになります。

プレイヤー用マルチカメラ UI

デモには Stage Camera Control Panel を配置します。既存シーンには
GameObject > SabaProps > Stage Camera Control Panel から追加できます。
生成時にシーン内のリグを登録します。操作対象と順序は Inspector の Rigs 配列で変更してください。

World Space Canvas の設置型パネルです。同じパネルを見ていても、操作内容とカメラ設定は
各プレイヤーのローカル状態であり、他のプレイヤーには反映されません。

操作動作
< CAM / CAM >操作するカメラと映像プレビューを切り替えます。各リグの設定は保持します
< PLAYER / PLAYER >対象候補をプレイヤー ID 順で選択します。表示名と ID を表示します
TRACK SELECTED / TRACK ME選択したプレイヤー、または自分を追従します
STOP FOLLOW追従を停止し、カメラを最後の姿勢で維持します
< SUBJECT / SUBJECT >顔・首・胸・体・左右の手足を切り替えます
BODY / WORLDアングルの基準を体の向き/ワールド固定で切り替えます
YAW / PITCH基準アングルを 5 度ずつ調整します
CLOSER / FURTHER距離を 0.25 m ずつ調整します。自動フレーミング中は画面占有率を 5 ポイントずつ変更します
AUTO FRAME / CAMERA WORK ON / OFF自動フレーミング/自動カメラワークを切り替えます。現在値は設定欄に表示します

プレイヤーの選択だけでは追従対象を変更しません。退出済みの対象に対する指定は無視し、
自動的に別人へ切り替えません。映像プレビューは既存の RenderTexture を使用します。
カメラの選択は操作先を切り替えるもので、他のカメラの描画停止や会場スクリーンの入力切替は行いません。

パネルは Water レイヤーに配置し、デモカメラの撮影対象から除外します。独自のカメラを使う場合も
同レイヤーを除外してください。パネル移動は Canvas の Transform で行えます。
手元への呼び出しと Global 同期は現時点では未実装です。

UI の Udon コンパイル、保存後のボタン接続、カメラごとの設定独立性は Unity EditMode テストで
検証します。VR/Desktop でのポインター操作とプレイヤー選択を含む実動作は VRChat で確認してください。


設定

構成

項目内容
Rig Root動かす Transform。未設定ならこの GameObject です
Framing Camera自動フレーミングが画角を読むカメラ。未設定なら子から探します
Handle手動補正に使う Pickup。未設定ならこの GameObject から探します

追従先

項目既定内容
Subject顔追う部位。下の表を参照してください
Follow Mode体基準0 でワールド基準、1 で被写体の体の向き基準
Target Local Player On Startオフ起動時にローカルプレイヤーを追い始めます

部位とフォールバックの対応です。VRChat は存在しないボーンに対して原点を返すため、
候補を順に試します。

Subject値第 1 候補第 2 候補第 3 候補最終
顔0Head頭のトラッキングNeckプレイヤー原点
首1NeckHeadChest頭のトラッキング
胸2ChestUpperChestSpine頭のトラッキング
体3HipsSpineChestプレイヤー原点
左手4LeftHand左手のトラッキングLeftLowerArm頭のトラッキング
右手5RightHand右手のトラッキングRightLowerArm頭のトラッキング
左足6LeftFootLeftLowerLegHipsプレイヤー原点
右足7RightFootRightLowerLegHipsプレイヤー原点

Neck と UpperChest は Humanoid でも省略できるため、必ずフォールバックが要ります。
非 Humanoid アバターではボーンが 1 つも取れないので、最終候補まで落ちます。

構図

項目既定内容
Orbit Yaw0基準からの方位角。0 が正面、90 が被写体から見て右手側
Orbit Pitch8仰角。正でカメラが上、被写体を見下ろします
Orbit Distance2.5被写体との距離 (m)。自動フレーミングが有効なら上書きされます
Subject Height Offset0注視点を部位から上下にずらす量 (m)

追従の滑らかさ

項目既定内容
Position Time Constant0.25位置が追いつくまでの時定数 (s)
Rotation Time Constant0.18向きが追いつくまでの時定数 (s)
Deadzone Radius0.02この半径 (m) 以内の被写体の揺れを無視します

時定数はフレームレートに依存しません。90 fps でも 45 fps でも同じ速さで追いつきます。

デッドゾーンはリモートプレイヤー特有の事情です。他人のボーン姿勢はネットワーク補間の
結果なので細かく震えており、そのまま追うとカメラが止まりません。

自動フレーミング

項目既定内容
Auto Framingオフ画面占有率が一定になるよう距離を調整します
Screen Fraction0.6被写体が縦方向に占める画面の割合
Subject Height Scale1.1目線の高さに掛けて被写体の大きさとする係数

VRChat はアバターの身長差が大きく、しかもアバタースケーリングで実行中に変わります。
距離を固定すると同じ設定でも被写体によって画面占有率が変わるため、身長を測って距離側を
動かします。Subject Height Scale は全身なら 1.1、顔寄りなら 0.2 程度が目安です。

自動カメラワーク

項目既定内容
Camera Workオフ被写体の周囲を自動で回り込みます
Camera Work Period24往復 1 周にかける時間 (s)
Camera Work Yaw Sweep90振り込む角度。90 で正面から真横まで
Camera Work Pitch Rise6振り込みと同時に上がる角度
Camera Work Dolly-0.4振り込みと同時に寄る距離 (m)。負で寄ります

3 つの動きは同じ位相を共有するので、回り込みながら迫り上がり、同時に寄る、という
クレーンの動きになります。折り返しと周期の境目で速度がゼロに落ちるため、端で急に
切り返すことはありません。

手動補正

項目既定内容
Allow Pickup AdjustオンPickup で掴んで動かすと、その構図が新しい定常アングルになります

掴んでいる間、スクリプトはカメラの姿勢を毎フレーム軌道パラメータへ焼き戻しています。
そのため「離す」ための特別な操作はありません。カメラワークが有効な場合はその寄与を
差し引いてから設定値に戻すので、振り込みの途中で掴んでも基準アングルはずれません。
自動フレーミングが有効な場合は、距離ではなく Screen Fraction の方へ焼き戻します。
距離を覚えても次のフレームで上書きされてしまうためです。


制限

  • リモートプレイヤーの姿勢は遅れます。 他人のボーンはネットワーク補間の結果で、 100〜200 ms 程度の遅延があります。これは VRChat の仕組み上どうにもなりません
  • roll は保持されません。 Pickup でカメラを傾けて離しても、水平に戻ります。 これは意図した挙動で、傾いた地平線が残らないようにしています
  • 同期しません。 0.2.0 まではローカル専用です
  • リアルタイムカメラは重い処理です。 RenderTexture へ描くカメラの同時稼働は 1〜2 台に抑え、カリングマスクと解像度を絞ってください

ライセンス

Apache License 2.0。全文は LICENSE.md を参照してください。