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