Constraints(制約)
VRChatには独自のカスタムConstraints(制約)システムが用意されており、アバターやワールド内のTransformを、他のTransformに対して相対的に移動、回転、拡大縮小させることができます。
これは、VRChatのアバターが通常どのように制約を使用するかを考慮しつつ、UnityのConstraintsシステムをほぼそのまま置き換えることを目的としています。Constraintsを使用したことがない場合は、UnityのConstraintsに関するドキュメントを参照すると理解の助けになります。
アバターを作成する際は、UnityのConstraintsではなく、VRChatのConstraintsを使用するようにしてください。アバターにUnityのConstraintsが含まれている場合、ゲーム内でアバターが読み込まれる際にVRChatのConstraintsへと自動的に変換されます。そのため、あらかじめVRChatのConstraintsを直接使用しておけば、アバターの実際の挙動をより正確に把握でき、パフォーマンスランクもより正確に算出されます。
ワールドに関しては、VRChatのConstraintsとUnityのConstraintsのどちらを使用しても、あるいは両方を組み合わせて使用することも可能です。UnityのConstraintsを一度にシーン内で多用しすぎると重大なパフォーマンス問題を引き起こす可能性があるため、使いすぎには注意してください。VRChatのConstraintsを使用すれば、追加のオプション機能を利用できるだけでなく、UnityのConstraintsを使用する場合と比べてワールドのパフォーマンスが向上する可能性があります。
このページでは、全体的な理解とアバターのパフォーマンスに焦点を当てています。Udonから、あるいはC#で記述されたSDKツールからConstraintsを操作したい場合は、VRChat ConstraintsのテクニカルAPIをご覧ください。
Constraint の種類
VRChat は現在、Unity に組み込まれている6種類の Constraint と同様に動作するように設計された、以下の Constraint タイプを提供しています。
- VRCAimConstraint - ソースの方向を向くようにターゲットの Transform を回転させます。どの方向を前方として扱うかをカスタマイズできます。
- VRCLookAtConstraint - ターゲットの Transform の正の Z 軸がソースの方向を向くように回転させる、簡略化された Aim Constraint です。
- VRCParentConstraint - ソースの子オブジェクトであるかのように、ターゲットの Transform を移動および回転させます。
- VRCPositionConstraint - ターゲットの Transform の位置がソースの位置と一致するように変更します。
- VRCRotationConstraint - ターゲットの Transform の回転がソースの回転と一致するように変更します。
- VRCScaleConstraint - ターゲットの Transform のスケールがソースのスケールと一致するように変更します。
各 Constraint タイプで利用可能な設定の詳細については、上記のリンク先を参照してください。
高度なコンストレイント設定
Advanced Settings(高度な設定)の折りたたみセクションには、VRChatコンストレイントによって提供される追加機能が含まれています。
Target Transform
Target Transform 設定では、このコンストレイントが対象とする Transform を変更できます。デフォルトではこの設定は空であり、コンストレイントはコンポーネントがアタッチされている Transform に適用されます。この Transform をアニメーションで変更することはできない点に注意してください。
この機能は、アバターやワールドのプレハブにあるすべてのコンストレイントコンポーネントを一箇所にまとめたい場合や、コンストレイントを使用するシステムを構築し、それを別のアバターやワールドプレハブ間で転送可能にしたい場合に役立ちます。
Solve In Local Space
通常、コンストレイントはワールド空間で計算されます。つまり、ソースの ワールド 座標の移動・回転・スケールに追従します。Solve In Local Space オプションを有効にすると、コンストレイントは代わりにソースの ローカル 座標の移動・回転・スケールに追従するようになります。
これは、アバター用に追加の義肢を設定するような状況で便利です。例えば、アバターの実際の腕の各ボーンを参照するローカル解決された回転コンストレイントのチェーンを作成すれば、実際の腕が動くのに合わせてそのチェーンを回転させることができます。ただし、これは回転コンストレイントに限ったことではなく、すべての種類のコンストレイントでローカル解決を使用できます。
以下の動画は、グローバル(ワールド空間)とローカルで計算される回転コンストレイントの違いを例として示しています。このクリップでは、中央と右の矢印がそれぞれ回転コンストレイントを使用して左の矢印の回転に追従していますが、中央の矢印はワールド空間解決を、右の矢印はローカル空間解決を使用しています。ワールド空間解決されたコンストレイントは、ターゲットの回転に常にワールド空間で追従していることに注目してください。対照的に、ローカル解決されたコンストレイントは、ターゲットが親ボーンに対して向いている向きに常に追従します。
Freeze To World
Freeze To World を有効にすると、コンストレイントはすべてのソースを無視し、ターゲットの Transform をワールド空間で固定します。Transform の移動・回転・スケールは、Freeze To World が無効になるまで維持されます。
この設定は、アバターのアニメーションやワールドの Udon スクリプトでオン/オフを切り替える際に最も効果を発揮します。例えば、アバターの場合:
Freeze To World用の エクスプレッションメニューのトグル を設定し、デフォルトでは無効にしておきます。- Animation Clip 内で
Freeze To Worldを有効にすると、その Transform はワールド空間に固定されます。 - Animation Clip 内で
Freeze To Worldを無効にすると、Transform は再びコンストレイントのソースに追従します。
これにより、アバターがワールド内の固定位置にオブジェクトを置くことができます。離れて歩いても、オブジェクトはアバターに追従しません。これには、ターゲットの Transform の移動と回転の両方をフリーズできる Parent Constraint が最も適しています。ただし、Freeze To World は他のすべてのコンストレイントタイプでも利用可能です。
ワールド内のコンストレイントでこの効果を実現するには、Animation Clip を使用する代わりに Udon スクリプトを使用して FreezeToWorld の値を変更します。
Freeze To World プロパティは、Constraint Settings セクションでフリーズ対象として選択された軸にのみ影響します。オブジェクトを完全にその場に静止させたい場合は、すべての軸をフリーズする必要があります。そうしない場合、それらの軸は更新されず、Transform はワールド空間で固定されたままにはなりません。
Freeze To World を有効にすることは、コンストレイントコンポーネント自体を無効にすることとは異なります!
- コンストレイントが無効な場合、影響を受ける Transform は ローカル 空間での動きを停止します。Transform は、それを含むオブジェクトの動き(例えば、アバターに適用されている場合はそのアバターの動き)には追従し続けます。
Freeze To Worldを有効にすると、コンストレイントが積極的に Transform をローカル空間で動かし、ワールド 空間で移動しないようにします。
さらに、Freeze To World がデフォルトでオンになっていると、コンストレイントはロードされた瞬間に、シーン内のその開始位置・回転・スケールで自分自身をフリーズさせます。これは、ワールド空間内の特定の場所・回転・スケールに確実に配置する方法ではありません。
Rebake Offsets When Unfrozen
Rebake Offsets When Unfrozenを有効にすると、Freeze To Worldが無効化されて制約(constraint)のフリーズが解除された際、元のオフセットを維持する通常の動作ではなく、ソースに対するオフセットを再計算するようになります。
この値自体を切り替えても何も起こりません。これは単に、Freeze To Worldが無効化されたときに何を行うべきかを決定する設定です。
パフォーマンス
このセクションはアバターに使用されるコンストレイント(制約)のみに適用されます。ワールドにはパフォーマンスランクが適用されないためです。
コンストレイントに関連するパフォーマンスカテゴリは2つあります。各プラットフォームに適用される制限については、Performance Ranks のページを参照してください。
コンストレイント数 (Constraint Count)
コンストレイント数は単純で、無効なものを含め、アバターに付与されているコンストレイントの合計数です。これには VRChat コンストレイントと Unity コンストレイントの両方が含まれます。Unity コンストレイントは、アバターがゲーム内で読み込まれる際に、自動的に VRChat コンストレイントに変換されます。
コンストレイントの合計数を減らすことで、アバターのパフォーマンスを向上させることができます。
コンストレイント深度 (Constraint Depth)
アバター上にコンストレイントの連鎖を設定する場合(例えば、追加された手足に沿って回転制約を連鎖させる場合など)、それらのコンストレイントは、連鎖の根本から先端にあるコンストレイントまで、特定の順序で1つずつ評価される必要があります。連鎖上に3つのコンストレイントがある場合、その連鎖のコンストレイント深度は3となります。アバター全体のコンストレイント深度の評価は、アバター全体で最も長い依存関係の連鎖に基づきます。
コンストレイント深度は、最も長いコンストレイントの連鎖の長さを短くすることで下げることができます。このカテゴリは、すべての連鎖の合計ではなく最も長い連鎖を探すという点に注意してください。例えば、アバターに深度3の腕が複数あったとしても、他の場所にもっと長い連鎖がなければ、アバター全体のスコアは3のままです。
コンストレイント深度は、単に合計数を数えるよりも、アバター上のコンストレイントがどのように動作するかをより正確に評価できるため重要です。コンストレイント間の依存関係を最小限に抑えるように構成することで、多くのコンストレイントを同時に実行できるようになり、順番に実行しなければならない状況と比較してパフォーマンスが向上します。
アバターのコンストレイント深度は、VRChat コンストレイントのみを使用している場合に正確に計算できます。
Unity コンストレイントが含まれている場合、Unity コンストレイントは一度に1つずつしか実行できないとみなされるため、コンストレイント深度が過大評価される可能性があります。SDK のコントロールパネルにある適切な Auto Fix オプションを使用することで、アバター上のすべての Unity コンストレイントを同等の VRChat コンストレイントに変換できます。
使用上のヒント
- 制約(Constraint)が動作しない場合は、正しく実行されているか確認してください。
Is Activeオプションが有効になっている必要があります。- コンポーネント自体が有効(名前の横のチェックボックスがオン)であり、アクティブなゲームオブジェクトにアタッチされている必要があります。
Lockオプションが有効であることを確認してください。無効の場合、制約はトランスフォームに影響を与える代わりに、自身のAt RestおよびOffset値を再評価してしまいます。
Target Transformへの参照は、アニメーションや Udon スクリプトによって変更することはできません。これは、制約のターゲットとなるトランスフォームの変更が、パフォーマンス向上のために実行時にキャッシュされるためです。制約のターゲットトランスフォームを変更したい場合は、代わりにそれぞれ異なるターゲットトランスフォームを持つ複数の制約コンポーネントを切り替えることを検討してください。- 可能であれば、制約によって参照されるトランスフォームをアニメーションや Udon スクリプトで変更しないでください。実行時にトランスフォームの参照を変更すると、参照が変わるたびに制約を再評価する必要があるため、アバターのパフォーマンスに悪影響を及ぼす可能性があります。
- これは特に、制約のトランスフォームに対する参照を変更することを指しており、トランスフォームの座標、回転、スケールをアニメーションさせることは問題ありません!
- アバターにおいて、技術的な制限により個々のソースのトランスフォーム参照をアニメーションさせることはできません。これに対するよりシンプルな代替案として、異なるトランスフォームを持つ複数のソースを設定し、それらのウェイト(Weight)をアニメーションさせる方法があります。
最終更新: