最近bd_さんによってリリースされたModular Avatarは、アバター改変において非破壊的なワークフローを導入でき非常に便利なツールとなっています。 自身でも仮想年賀状鳴子の配布パッケージに利用させていただいているのですが、今回はこれらのパッケージに実装したワールド固定の仕組みについて解説します。

Modular Avatarの仕組み

Modular Avatarはアバターのデータがビルドされる手前でオブジェクトのパス修正やアニメーションの統合、パラメーター名の変更などを行い、統合・変更後のデータに自動的に差し替えを行うことで、既存のファイルを変更することなく改変内容を適用するような仕組みとなっています。 これによりアバター本体と小物ギミックのリソースファイルを綺麗に分離しやすくなるため、メンテナンス性の向上や、配布用パッケージの作成の省力化ができ、非常に便利です。

今回の解説ではModular Avatarが提供するBone ProxyMenu InstallerMerge AnimatorParametersの4種類のコンポーネントを利用してワールド固定を含んだパッケージの作成を行っていきます。 この解説では各コンポーネントの詳細については扱わないので、必要に応じてマニュアルページをご参照ください。

0. Modular Avatarの導入

リリース一覧ページから最新のModular AvatarのUnit Packageをダウンロードし、プロジェクトにインポートしてください。 執筆時の最新版は 1.2.0 です。

1. ワールド固定用Prefabの作成

ワールド固定は何通りかやり方があるのですが、Modular Avatarで設定を行って配布すると考えた場合、空のGameObjectのみを含むPrefabを作成し、シーンには配置せずParent Constraintのソースに指定する手法が適しています。

  1. まずはヒエラルキーウィンドウを右クリックし、 Create Empty を選択して空オブジェクトを作成します。
  2. 作成後にTransformをリセットし、位置や角度を0に揃えます。また、オブジェクトの使用用途から WorldAnchor という名前に変更しています。
空GameObjectの作成 空GameObjectの作成

作成したオブジェクトをプロジェクトウィンドウにドラッグ&ドロップし、Prefab化します。ここでは Assets/XiPHiA/Common/Prefabs 以下に作成しています。

Prefabの作成 Prefabの作成

Prefab化ができたらシーン上では必要が無いので、ヒエラルキーウィンドウから WorldAnchor オブジェクトを削除しておきます。

2. ギミック用のオブジェクトの配置

ここからはアバターを使いながら作業を進めていきます。この解説ではSDKに付属するサンプルアバター( Packages/VRChat SDK - Avatars/Samples/Dynamics/Robot Avatar/Tutorial_Robot_Avatar_Dynamics_Demo_v1.prefab )を使用して説明を行います。

アバターオブジェクトの直下にギミック用のオブジェクトを作成します。ここでは GimmickRoot としています。

ギミック用オブジェクトの作成 ギミック用オブジェクトの作成

作成したギミック用のオブジェクトにParent Constraintを追加し、先ほど作成したワールド固定用Prefabをソースに設定します。

Parent Constraintの設定 Parent Constraintの設定

Parent Constraintは以下の表のとおりの設定となります。

設定項目 設定内容
Is Active オン
Weight 1
Constraint Settings / Lock オン
Constraint Settings / Position At Rest 0, 0, 0
Constraint Settings / Rotation At Rest 0, 0, 0
Constraint Settings / Position Offset (WorldAnchor) 0, 0, 0
Constraint Settings / Rotation Offset (WorldAnchor) 0, 0, 0
Constraint Settings / Freeze Position Axes 全てオン
Constraint Settings / Freeze Rotation Axes 全てオン
Sources WorldAnchor, ウェイト1

2-1. ハンドボーン追従オブジェクトの作成

作成したギミック用のオブジェクト直下に手の位置や姿勢に追随させるためのオブジェクトを作成します。ここでは HandRef としています。

ハンドボーン追従オブジェクトの作成 ハンドボーン追従オブジェクトの作成

作成したオブジェクトにMA Bone Proxyを追加し、追従させたい手のボーンを Target(ターゲット) にドラッグ&ドロップします。 そのあと、 Attachment Mode(配置モード)As child; at root(子として・ルートに配置) に設定します。

追従先ボーンの設定 追従先ボーンの設定

2-2. 小物配置用オブジェクトの作成

作成したギミック用のオブジェクト直下に小物を配置するためのオブジェクトを作成します。ここでは Pivot としています。

小物配置用オブジェクトの作成 小物配置用オブジェクトの作成

作成したギミック用のオブジェクトにParent Constraintを追加し、先ほど作成したハンドボーン追従オブジェクトをソースに設定します。

Parent Constraintの設定 Parent Constraintの設定

Parent Constraintは以下の表のとおりの設定となります。

設定項目 設定内容
Is Active オン
Weight 1
Constraint Settings / Lock オン
Constraint Settings / Position At Rest 0, 0, 0
Constraint Settings / Rotation At Rest 0, 0, 0
Constraint Settings / Position Offset (WorldAnchor) 0, 0, 0
Constraint Settings / Rotation Offset (WorldAnchor) 0, 0, 0
Constraint Settings / Freeze Position Axes 全てオン
Constraint Settings / Freeze Rotation Axes 全てオン
Sources HandRef, ウェイト1

2-3. 小物の配置と位置調整

先ほど作成した小物配置用オブジェクト直下にワールド固定したい小物を配置します。ここでは縮小したCubeを配置し、手のひらの上に来るように位置を調節しています。また、Box Colliderを削除しています。

小物の配置 小物の配置

3. ワールド固定ギミックの実装

オブジェクト配置と基本的な設定は完了したので、ここからギミックの実装に入ります。

3-1. アニメーションコントローラーの作成

ギミックの状態管理に使用するアニメーションコントローラーを作成します。プロジェクトウィンドウの右ペインを右クリックし、 Create -> Animation Controller を選択します。 ここでは Assets/XiPHiA/Gimmick/Animations/Contorllers 以下に GimmickController として作成しています。

制御用アニメーションコントローラーの作成 制御用アニメーションコントローラーの作成

3-2. アニメーターの設定

ギミック用オブジェクト( GimmickRoot ) にAnimatorを追加し、先ほど作成したアニメーションコントローラーを Controller に設定します。

Animatorの設定 Animatorの設定

3-3. アニメーションコントローラーの設定

3-3-1. 制御用パラメーターの追加

3-1. で作成したアニメーションコントローラーを設定します。まずはAnimatorウィンドウのParameterタブを開き、 Bool 型のパラメーターとして、 ActiveDrop の2つを追加します。 Active はオブジェクトの表示・非表示の切り替え、 Drop はワールド固定と手持ちの切り替えに使用します。

制御用パラメーターの設定 制御用パラメーターの設定

3-3-2. 表示・非表示用アニメーションの作成

表示・非表示を切り替えるために使用するアニメーションを作成します。プロジェクトウィンドウの右ペインを右クリックし、 Create -> Animation を選択します。 ここでは Assets/XiPHiA/Gimmick/Animations/Clips 以下に ActiveInactive として2つ作成しています。

表示・非表示用アニメーションの作成 表示・非表示用アニメーションの作成

3-3-3. 表示・非表示切り替えレイヤーの設定

  1. AnimatorウィンドウのLayerタブを開き、初期レイヤーである Base LayerActive に名前を変更し、 Inactive ステート と Active ステートの2つを追加します。
  2. 作成したステートの Motion3-3-2. で作成した対応する名前のアニメーションを設定します。
  3. Inactive ステートをデフォルトステートに設定し、 Entry ステートから Active ステートへのトランジションと、 Inactive ステートと Active ステート間の両方向にトランジションを追加します。
    • Entry ステートから Active ステートへのトランジション遷移条件に Active パラメーターを追加し、条件値を false に設定します。
    • Inactive ステートから Active ステートへのトランジション遷移条件に Active パラメーターを追加し、条件値を false に設定します。
    • Active ステートから Inactive ステートへのトランジション遷移条件に Active パラメーターを追加し、条件値を true に設定します。

Activeレイヤーの設定 Activeレイヤーの設定
ステート・トランジションの設定 ステート・トランジションの設定

各ステートとトランジションの設定は以下のようになります。

Inactiveステート
設定項目 設定内容
Motion Inactive
Speed 1
Multiplier オフ
Motion Time オフ
Mirror 全てオフ
Cycle Offset 0, オフ
Foot IK オフ
Write Defaults オフ
Activeステート
設定項目 設定内容
Motion Active
Speed 1
Multiplier オフ
Motion Time オフ
Mirror 全てオフ
Cycle Offset 0, オフ
Foot IK オフ
Write Defaults オフ
Entry -> Activeへのトランジション
設定項目 設定内容
Conditions / Active true
Inactive -> Activeへのトランジション
設定項目 設定内容
Has Exit Time オフ
Settings / Exit Time 0
Settings / Fixed Duration オン
Settings / Transition Durasion (s) 0
Settings / Transition Offset 0
Settings / Interruption Source None
Settings / Ordered Interruption オン
Conditions / Active true
Inactive -> Activeへのトランジション
設定項目 設定内容
Has Exit Time オフ
Settings / Exit Time 0
Settings / Fixed Duration オン
Settings / Transition Durasion (s) 0
Settings / Transition Offset 0
Settings / Interruption Source None
Settings / Ordered Interruption オン
Conditions / Active false

3-3-4. 表示・非表示切り替えアニメーションの設定

3-3-2. で作成したアニメーションを設定します。 2. で作成したギミック用のオブジェクトを選択した状態で、Animationウィンドウを開きます。

表示・非表示切り替えアニメーションの設定 表示・非表示切り替えアニメーションの設定
  1. Inactive アニメーションを選択した状態で、Add Propertyボタンを押してPivot -> 2-3で配置した小物(ここでは Cube) -> Is Activeを追加します。
  2. プロパティ―名横のチェックボックスをオフにし、1:00地点に追加されたキーフレームを削除します。
  3. Active アニメーションを選択した状態で、1. と同じようにAdd Propertyボタンを押してPivot -> 2-3で配置した小物(ここでは Cube) -> Is Activeを追加します。
  4. プロパティ―名横のチェックボックスをオンのままにし、1:00地点に追加されたキーフレームを削除します。

Inactiveアニメーションの設定 Inactiveアニメーションの設定
Activeアニメーションの設定 Activeアニメーションの設定

3-3-5. ワールド固定用アニメーションの作成

ワールド固定・手持ちを切り替えるために使用するアニメーションを作成します。 3-3-2. と同じようにプロジェクトウィンドウの右ペインを右クリックし、 Create -> Animation を選択します。 ここでは Assets/XiPHiA/Gimmick/Animations/Clips 以下に DropHold として2つ作成しています。

ワールド固定用アニメーションの作成 ワールド固定用アニメーションの作成

3-3-6. ワールド固定・手持ち切り替えレイヤーの設定

  1. AnimatorウィンドウのLayerタブを開き、新規に Drop レイヤーを作成し、レイヤーのウェイトを1に設定します。
  2. Hold ステート と Drop ステートの2つを追加します。
  3. 作成したステートの Motion3-3-5. で作成した対応する名前のアニメーションを設定します。
  4. Hold ステートをデフォルトステートに設定し、 Entry ステートから Drop ステートへのトランジションと、 Hold ステートと Drop ステート間の両方向にトランジションを追加します。
    • Entry ステートから Drop ステートへのトランジション遷移条件に Drop パラメーターを追加し、条件値を false に設定します。
    • Hold ステートから Drop ステートへのトランジション遷移条件に Drop パラメーターを追加し、条件値を false に設定します。
    • Drop ステートから Hold ステートへのトランジション遷移条件に Drop パラメーターを追加し、条件値を true に設定します。

Dropレイヤーの設定 Dropレイヤーの設定
ステート・トランジションの設定 ステート・トランジションの設定

各ステートとトランジションの設定は以下のようになります。

Holdステート
設定項目 設定内容
Motion Hold
Speed 1
Multiplier オフ
Motion Time オフ
Mirror 全てオフ
Cycle Offset 0, オフ
Foot IK オフ
Write Defaults オフ
Dropステート
設定項目 設定内容
Motion Drop
Speed 1
Multiplier オフ
Motion Time オフ
Mirror 全てオフ
Cycle Offset 0, オフ
Foot IK オフ
Write Defaults オフ
Entry -> Dropへのトランジション
設定項目 設定内容
Conditions / Drop true
Hold -> Dropへのトランジション
設定項目 設定内容
Has Exit Time オフ
Settings / Exit Time 0
Settings / Fixed Duration オン
Settings / Transition Durasion (s) 0
Settings / Transition Offset 0
Settings / Interruption Source None
Settings / Ordered Interruption オン
Conditions / Drop true
Drop -> Holdへのトランジション
設定項目 設定内容
Has Exit Time オフ
Settings / Exit Time 0
Settings / Fixed Duration オン
Settings / Transition Durasion (s) 0
Settings / Transition Offset 0
Settings / Interruption Source None
Settings / Ordered Interruption オン
Conditions / Drop false

3-3-7. 表示・非表示切り替えアニメーションの設定

3-3-5. で作成したアニメーションを設定します。2. で作成したギミック用のオブジェクトを選択した状態で、Animationウィンドウを開きます。

  1. Hold アニメーションを選択した状態で、Add Propertyボタンを押してPivot -> Parent Constraint -> Activeを追加します。
  2. プロパティ―名横のチェックボックスをオンのままにし、1:00地点に追加されたキーフレームを削除します。
  3. Drop アニメーションを選択した状態で、1. と同じようにAdd Propertyボタンを押してPivot -> Parent Constraint -> Activeを追加します。
  4. プロパティ―名横のチェックボックスをオフにし、1:00地点に追加されたキーフレームを削除します。

Holdアニメーションの設定 Holdアニメーションの設定
Dropアニメーションの設定 Dropアニメーションの設定

4. Modular Avatarの設定

ギミックの実装が完了したので、Modular Avatarによる設定を行っていきます。

4-1. Merge Animatorの設定

  1. 2. で作成したギミック用のオブジェクト(ここでは GimmickRoot )にMA Merge Animatorを追加し、 3-1. で作成したアニメーションコントローラー(ここでは GimmickController)を Animator to merge(統合されるアニメーター) にドラッグ&ドロップします。
  2. Delete attached animator(付属アニメーターを削除) と Match Avatar Write Defaults(アバターのWrite Defaults設定に合わせる) にチェックを入れます。
アニメーターの統合設定 アニメーターの統合設定

4-2. Parametersの設定

  1. 2. で作成したギミック用のオブジェクト(ここでは GimmickRoot )にMA Parameterを追加し、 Show Prefab Developer Options(プレハブ開発者向け設定を表示) にチェックを入れます。
  2. 3-3-1. で設定したパラメーターがリストに表示されるので、それぞれ Internal(内部値) にチェックを入れ、 Sync Mode(同期モード)Bool に設定します。
パラメーターの設定 パラメーターの設定

4-3. Menu Installerの設定

4-3-1. メニュー追加用Expression Menuの作成

ワールド固定などの操作を行うメニューを作成します。

  1. プロジェクトウィンドウの右ペインを右クリックし、 Create -> VRChat -> Avatars -> Expressions Menu を選択します。
    • ここでは Assets/XiPHiA/Gimmick/ExpressionMenu 以下に GimmickMenu として作成しています。
  2. インスペクターのAdd Controlボタンからメニューを追加し、 NameActive に設定します。
    • TypeToggle に設定し、 Parameter の右側のテキストボックスに Active と入力します。
      • Parameter not found on the active avatar descriptor. と表示されますが問題ありません。
  3. 再度インスペクターのAdd Controlボタンからメニューを追加し、 NameDrop に設定します。
    • TypeToggle に設定し、 Parameter の右側のテキストボックスに Drop と入力します。
      • こちらも Parameter not found on the active avatar descriptor. と表示されますが問題ありません。
ギミック用メニューの作成 ギミック用メニューの作成

続いて上位階層用のメニューを作成します。

  1. プロジェクトウィンドウの右ペインを右クリックし、 Create -> VRChat -> Avatars -> Expressions Menu を選択します。
    • ここでは Assets/XiPHiA/Gimmick/ExpressionMenu 以下に RootMenu として作成しています。
  2. インスペクターのAdd Controlボタンからメニューを追加し、 NameGimmick に設定します。
    • TypeSub Menu に設定し、 Sub Menu に先ほど作成した GimmickMenu をドラッグ&ドロップします。
上位階層メニューの作成 上位階層メニューの作成

4-3-2. Menu Installerコンポーネントの追加

  1. 2. で作成したギミック用のオブジェクト(ここでは GimmickRoot )にMA Menu Installerを追加します。
  2. Prefab Developer Options(プレハブ開発者向け設定) を展開し、 Menu to Install(インストールされるメニュー)4-3-1. で作成した上位階層用のメニュー(ここでは RootMenu)をドラッグ&ドロップします。
メニューの設定 メニューの設定

5. 仕上げ

以上でワールド固定が可能な小物出し入れギミックの実装が完了しました。最後にModular Avatarのチュートリアルで推奨されているように、コンポーネントの並び替えを行います。 Menu Installer、Parameters、Merge Animatorの順で先頭から並ぶよう調整します。

コンポーネントの並び替え コンポーネントの並び替え

最後にギミック用のオブジェクト(ここでは GimmickRoot )をPrefab化します。ここでは Assets/XiPHiA/Gimmick/Prefabs 以下に作成しています。

Prefab化 Prefab化

あとは GimmickRoot Prefabを選択してExport Packageを行うことで、Modular Avatarに対応したワールド固定ができる、出し入れ可能な小物として配布することが可能になります。