SabaProps Stage Cam
ワールド側から特定のプレイヤーの部位を追い、一定距離と固定アングルを保つ Udon カメラリグです。
ステージのある種のワールドで、演者を追い続けるカメラを置くことを想定しています。
- 追える部位は顔・首・胸・体・左右の手・左右の足の 8 種類
- アングルは被写体の体の向きを基準にも、ワールド固定にも取れます
- Pickup で掴んで構図を直すと、その位置が新しい定常アングルになります
- 被写体の周囲を自動で回り込むクレーン風のカメラワーク
- アバターの身長差を吸収する自動フレーミング
0.2.0 まではローカル専用です。各クライアントが自分の見たい対象を自分で追います。
全員で同じ画を見る運用は 0.3.0 で入れます(ロードマップ)。

同梱Sample SceneをUnity 2022.3で表示した画面です。ステージ、2台のカメラ、2枚のWorld Screenを確認できます。
追従対象と 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 付きのリグを配置できます。
個別に構成する場合は以下の手順を使用します。
- 空の GameObject に
SabaProps/Stage Cam Rigを追加します - その子に
Cameraを置き、Target Textureに RenderTexture を割り当てます - RenderTexture を貼ったマテリアルで、ワールドにスクリーンを置きます
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 候補 | 最終 |
|---|---|---|---|---|---|
| 顔 | 0 | Head | 頭のトラッキング | Neck | プレイヤー原点 |
| 首 | 1 | Neck | Head | Chest | 頭のトラッキング |
| 胸 | 2 | Chest | UpperChest | Spine | 頭のトラッキング |
| 体 | 3 | Hips | Spine | Chest | プレイヤー原点 |
| 左手 | 4 | LeftHand | 左手のトラッキング | LeftLowerArm | 頭のトラッキング |
| 右手 | 5 | RightHand | 右手のトラッキング | RightLowerArm | 頭のトラッキング |
| 左足 | 6 | LeftFoot | LeftLowerLeg | Hips | プレイヤー原点 |
| 右足 | 7 | RightFoot | RightLowerLeg | Hips | プレイヤー原点 |
Neck と UpperChest は Humanoid でも省略できるため、必ずフォールバックが要ります。
非 Humanoid アバターではボーンが 1 つも取れないので、最終候補まで落ちます。
構図
| 項目 | 既定 | 内容 |
|---|---|---|
Orbit Yaw | 0 | 基準からの方位角。0 が正面、90 が被写体から見て右手側 |
Orbit Pitch | 8 | 仰角。正でカメラが上、被写体を見下ろします |
Orbit Distance | 2.5 | 被写体との距離 (m)。自動フレーミングが有効なら上書きされます |
Subject Height Offset | 0 | 注視点を部位から上下にずらす量 (m) |
追従の滑らかさ
| 項目 | 既定 | 内容 |
|---|---|---|
Position Time Constant | 0.25 | 位置が追いつくまでの時定数 (s) |
Rotation Time Constant | 0.18 | 向きが追いつくまでの時定数 (s) |
Deadzone Radius | 0.02 | この半径 (m) 以内の被写体の揺れを無視します |
時定数はフレームレートに依存しません。90 fps でも 45 fps でも同じ速さで追いつきます。
デッドゾーンはリモートプレイヤー特有の事情です。他人のボーン姿勢はネットワーク補間の
結果なので細かく震えており、そのまま追うとカメラが止まりません。
自動フレーミング
| 項目 | 既定 | 内容 |
|---|---|---|
Auto Framing | オフ | 画面占有率が一定になるよう距離を調整します |
Screen Fraction | 0.6 | 被写体が縦方向に占める画面の割合 |
Subject Height Scale | 1.1 | 目線の高さに掛けて被写体の大きさとする係数 |
VRChat はアバターの身長差が大きく、しかもアバタースケーリングで実行中に変わります。
距離を固定すると同じ設定でも被写体によって画面占有率が変わるため、身長を測って距離側を
動かします。Subject Height Scale は全身なら 1.1、顔寄りなら 0.2 程度が目安です。
自動カメラワーク
| 項目 | 既定 | 内容 |
|---|---|---|
Camera Work | オフ | 被写体の周囲を自動で回り込みます |
Camera Work Period | 24 | 往復 1 周にかける時間 (s) |
Camera Work Yaw Sweep | 90 | 振り込む角度。90 で正面から真横まで |
Camera Work Pitch Rise | 6 | 振り込みと同時に上がる角度 |
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 を参照してください。