[VRChat] Avatars3.0解説（概要編）

こんにちは。一般VRChatterのNitRoです。

普段はフツーにVRChatでまったりしたり、ゲームワールドであそんだり、ワールド作ったり、アバターにギミック詰め詰めしたりなどして過ごしています。

たまにフレンドにアバター改変を教える時があるのですが、もう少しだけAvatars3.0の仕組みを理解できていればアイデアをドンドコ形にできるのになといつも思っています。

というわけで今回は、●●の実装方法～！ではなくてAvatars3.0及びそこで使うAnimatorControllerの仕組みに重点を置いて記事を書いてみようかと思った次第であります。これを読めばアバター改変力が上がる！応用力がつく！そんな記事を目指していきたいです。

__本記事は、他の記事を見たりフレンドに教えてもらったりしながらAvatars3.0でアバター改変したことあるけど結局何やってんのかよくわかんねーーー！！自分でイジるとすぐバグる！！助けて！！というVRChat初級者～中級者の方が対象です。__

横文字が多いですが単なる用語です。怖がらずについてきてください。

# Avatars3.0の全貌
いいですか皆さん。Avatars3.0とはピタゴラスイッチです。
まず、下図を見てください。
![AV3.0_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/f6e71534-e3e8-bf2d-537a-8ef34049031c.png)
ざっくりですがこれがAvatars3.0の仕組みです。

①　アクションメニュー（リング状のやつ）にて押されたボタンにより、アバターに設定されたパラメータ(VRCExpressionParameters)の値が変更される。

②　VRCExpressionParametersに設定されているパラメータはAnimatorのParametersと値を共有する。

③　AnimatorのParametersの値が②によって変更されたことにより、Animatorのステートが切り替わる。

④　現在のステートに設定されている、Animationファイルが再生される。

⑤　再生されているAnimationファイルの影響を受けてアバターが動く。

ワケワカメだと思うので一個ずつ説明します。

## ①　アクションメニュー（リング状のやつ）にて押されたボタンにより、アバターに設定されたパラメータ(VRCExpressionParameters)の値が変更される。

3DモデルをアバターとしてVRChatにアップロードするためには、必ず`VRCAvatarDescriptor`というコンポーネントを追加する必要があります。
これ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/ca5fa1dc-019f-2e75-c890-fef8d0281280.png)


その`VRCAvatarDescriptor`には様々な設定項目があり、その中に`Expressions`(表現)というものがあります。
`Expressions`には以下の2つのものを設定できます。

__1. Menu__
`VRCExpressionsMenu`というファイルを割り当てられます。
アクションメニューのExpressions以下の階層のボタンを司ります。
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/6eeae60e-a126-fdb5-d83d-41e1702f37d8.png)

__2. Parameters__
`VRCExpressionParameters`というファイルを割り当てられます。
Menuの操作によって直接操作される数値の設定です。
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/cadc19d1-67ed-cabe-8ca0-5867d66f655c.png)


※`▼Expressions`の下の`Customize`をクリックするとこんな画面になります。↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/25a3448e-f90a-887c-f930-35713206043e.png)
__ここで言いたいのは、`VRCExpressionsMenu`によって設定されたボタンを操作することによって、`VRCExpressionParameters`に設定されたパラメータの数値を弄ることができるということです。__

### パラメータとはなんぞや？
プログラミングに触れたことのない方、 __パラメータとはなんぞや？__ となっているかもしれません。
ここで言うパラメータと言うのは __数値が一つ入る箱__ をイメージしてもらえればよいです。
`VRCExpressionParameters`上にいくつか名前のついた箱を用意しておき、アクションメニュー等からの入力によってその箱の中に入っている数値を切り替えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/39b030ac-d374-e49f-5441-6d0d47cb2ea0.png)


`VRCExpressionParameters`に設定できるパラメータには以下のような種類があります。
#### パラメータの型の種類
| 型(Type) | 入ることができる数値 | 使うシチュエーション | サイズ |
|:-:|:-:|:-:|:-:|
| int | 整数 (0,1,2,3...,255)  | 数種類の状態を切り替える | 8 |
| float | 小数を含む数値 (-1.0～1.0 ) | 滑らかに状態を推移させる | 8 |
| bool | オンかオフか (true, false) | オンとオフを切り替える | 1 |

intのパラメータには、0～255の範囲の整数のうち1つどれかが入ります。
floatのパラメータには、-1.0～1.0の範囲の数値のうち1つどれかが入ります。
boolのパラメータには、trueかfalseかのいずれかのうち1つの数値が入ります。

#### true？false？
数値？boolだけtrueとかfalseって英語やんけペテン師め！！とお思いの方、
true、falseという数値なんです。そういうもんなんです。0か1かで表現されることもあります。
因みにtrueというのは真、falseというのは偽という意味です。
が、日本語にしてもイミフなのでオン、オフと言う捉え方で問題ありません。trueがオンでfalseがオフです。
__大事なのは、boolには2種類の数値しか入り得ないということです。__

#### 型の選び方
作るギミックにもよりますが私はintとboolを使うことが多いです。
特に着せ替え関連なんかではintとboolの登場頻度が高いです。

例えば、intは0～255までの数値を扱えるので、数種類の服の切り替えなんかに使います。
以下のように服装に番号を振っていくイメージですね。

> 0: デフォ服
1: 夏服
2: 冬服
3: パジャマ
4: 水着 

boolは2値しか扱えないので、アクセサリのオンオフなんかによく使っています。
> false: ピアス off
true: ピアス on

賢い方はお気づきかもしれませんが、オンとオフの切替はintでも実装できます。
以下のようにすれば。
> 0: ピアス off
1: ピアス on

じゃあなんでbool使うの？ってハナシなんですが、これは上記の表の右端に記載した「サイズ」という数字が関わってきます。
実は、`VRCExpressionParameters`には無尽蔵にパラメータを追加作成できるわけではないのです。
サイズが ~~128~~ に収まるようにパラメータを作成する必要があります。  
**(2025年現在では256まで使えるようになりました！)**  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/3d130018-82b4-b549-0a82-9b5bf45e51f3.png)
数種類の状態を切り替えたいときはint、オンとオフだけを切り替えたいときはboolと覚えてください。

#### 例
　例1) 4種類の靴を履き替えたい→ int
　例2) 1種類のジャケットを着たり脱いだりしたい→ bool

#### 問題
次の場合はどの型のパラメータを使用すればよいでしょうか。
　問1) 5種類のヘアスタイルを切り替えたい

　問2) 1種類の眼鏡を掛けたり外したりしたい

　問3) 4種類のジャケットを切り替えたり、脱いだりしたい

　回答は最後に記載します。

## ②　VRCExpressionParametersに設定されているパラメータはAnimatorのParametersと値を共有する
ややこしいことに、`VRCExpressionsParameters`の他にも、`Animator`にも`Parameters`という設定項目が存在します。
__この2つの`Parameters`は、互いに連動しています。__

何言ってるかわからないかもしれませんが、`VRCExpressionsParameters`と`Animator`の`Parameters`が連動しているとだけ覚えてください。

例えば、`VRCExpressionsParameters`の`a`というパラメータの中身が変われば、`Animator`の`Parameters`の`a`というパラメータの中身も同じ値に変わります。逆も然り。

## ③　AnimatorのParametersの値が②によって変更されたことにより、Animatorのステートが切り替わる。

何言ってんだーーーー！！！
解説しましょう。

### てかAnimatorって誰ぞ？
Unityの世界に存在するAnimatorControllerという設定ファイルです。
Unity上のメニューバーから、`Window`→`Animation`→`Animator`と選択すると出てくる画面にてファイルの中身を確認できます。
__AnimatorではAnimationの状態遷移と、遷移条件となるパラメータを設定することが出来ます。__
VRChatではこのAnimatorを、1アバターにつき全部で8個セットすることが出来ます。
8個にはそれぞれ別々の役割がありますが、中身は全ておんなじAnimatorです。
VRChatが独自に設定している制約はありますが一旦忘れてください。

#### 状態遷移？？？？
こういうやつです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/21a6b7ad-81e9-6901-cf33-36cc64c088a8.png)
### オゲー！！！！

落ち着いてください。
何やら四角形同士が矢印の線で結ばれています。
四角形のことを`State(ステート)`、矢印のことを`Transition(トランジション)`と呼びます。

`State`とは __状態__ という意味の英語です。`Transition`とは __遷移__ という意味の英語です。
繋がってきましたね。

Animatorの状態遷移というのは、要するに __Yes/Noチャート__ です。(ggってみてください)
`State`を`Transition`でつないでYes/Noチャートを作ります。
Yes/Noチャートとちょっと違うところがあるとすれば、__四角の中ではなく矢印の中に質問が書いてある点でしょうか。__

`Transition`には __条件__ を設定できます。
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/dc41e0db-f37c-f3bb-ba19-b20411077a16.png)
>これは「Faceというパラメータが1と等しいとき」という条件。

その条件というのに、`Animator`画面内の`Parameters`に設定できるパラメータを使用します。
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/72face21-c016-bd55-ee18-6afe21fd1cb5.png)


パラメータの値に応じて、次に向かうステートが決定するということです。
下図では以下のようになります。
`Entry`からスタートして、`State A`に行きます。
そして以下の3つの道に分岐します。
・`paramA`というパラメータの値が`0`のとき、`State B`へ移動
・`paramA`というパラメータの値が`1`のとき、`State C`へ移動
・`paramA`というパラメータの値が`2`のとき、`State D`へ移動
その後、`Exit`に移動して処理が終了します。
`Exit`に行くと再びEntryからスタートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/8949cf24-856e-b406-eef0-244f3ade3112.png)

この辺りの状態遷移の組み方については別途記事を書こうと思っています。
お楽しみに。

## ④　現在のステートに設定されている、Animationファイルが再生される。
③で説明したように、Animatorの状態遷移はYes/NoチャートのようにState間を移動します。
StateにはAnimationファイルを設定することが出来ます。(`Motion`のところです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/487b7b61-e593-a447-26cc-5523d53e0b91.png)
状態遷移によって通ったStateに設定されたAnimationが再生されるわけです。
どこかのStateで待機している場合は、そのStateに設定されているAnimationが再生され続けます。

## ⑤　再生されているAnimationファイルの影響を受けてアバターが動く。
Animationファイルに設定されているとおりにアバターがアニメーションします。
Animationファイルは縦軸にオブジェクトやシェイプキー等のアニメーションさせる要素、横軸にフレーム(時間)という構成の画面をしています。
フレームというのは時間の単位です。設定によりけりではありますが、デフォルトでは60フレーム=1秒になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/e95d497a-d412-00b8-f660-3938ba1b391b.png)
時間軸ごとに数値を入れていくことで、物体をアニメーションさせることが出来ます。
便利なことに、1フレームずつ細かに数値を入れていく必要はありません。
例えば、0フレーム目に0、60フレーム目に100という数値を入れた場合、0フレーム目から60フレーム目にかけて、いい感じに数値を補完してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/d115c183-7509-2d4b-233d-368c68a7d5db.png)
上の図は、GameObjectのPosition.xに対して、0フレーム目を0、60フレーム目を100に設定しています。
濃い白の縦線の位置が再生位置です。30フレーム目のPosition.xの値を確認すると50となっていることがわかります。
どのように数値が補完されているかというのは、Animation画面の下部、`Curves`というところをクリックすると確認することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/87f2f8b5-b431-be48-e7db-862e79f968c5.png)
0からゆっくりと増加して徐々に増加率が上がり、100に近づくと増加率が緩やかになってゆっくりと100になる動きになっています。
このカーブは編集できます。
例えば、0から100までを直線で結べば、常に一定の速度でPosition.xが変化するようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/05743374-dc98-5e9e-9743-3b5a2042a524.png)


# まとめ
ここまで読んでいただいてありがとうございます。
このように、Avatars3.0は、VRCExpressionsMenu、VRCExpressionParameters、Animator、Animationの大きく4つの要素によってアバターを動かしています。
この4人の登場人物がどのように作用しあっているか頭に入っているだけで、Avatars3.0に関する他の記事を読んだときや、フレンドから教えてもらっているときの理解度が変わってくるんじゃないかなと思っています。
この記事が皆さんの助けになれば幸いです。
では！

# 追伸
実は、Avatars3.0のシステムではアクションメニュー以外からも入力を受け付けています。
一番わかり易いのがコントローラです。VR中に君が両手に持っているそれです。
この場合は以下のようなフローになります。
![AV3.0_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436991/49ebe01d-69bf-b9c4-ee47-7f78c1aba9ef.png)
コントローラからのハンドサインの入力の場合、VRCExpressionParametersを介さず直接AnimatorのParametersを操作することが出来ます。
この場合、VRChatがデフォルトで用意しているパラメータを使って実装します。
簡単に言うと、以下の名前のパラメータをAnimatorのParameterとして用意しておくと、ハンドサインの変化を状態遷移の条件に使用できるということです。
　・GestureLeft　・・・左手ハンドサイン
　・GestureRight　・・・右手ハンドサイン
他にもハンドサインのようにVRChatがデフォルトで用意しているパラメータがあります。どんなのが有るの？と気になった方、
ドキュメントを読みましょう！
[VRChat Documentation -Animator Parameters](https://docs.vrchat.com/docs/animator-parameters)

# 問題の回答
#### 問題
次の場合はどの型のパラメータを使用すればよいでしょうか。
　問1) 5種類のヘアスタイルを切り替えたい
　　正解はint。0～4の5つの数値を使うことで、5種類のヘアスタイルを切り替えることが出来ます。

　問2) 1種類の眼鏡を掛けたり外したりしたい
　　正解はbool。眼鏡をオン・オフできれば良いので、2値を扱うboolで十分です。

　問3) 4種類のジャケットを切り替えたり、脱いだりしたい
　　正解はint。実装方法にもよりますが、一番シンプルなのは4種類のジャケットと脱ぎ状態の、5つの状態を切り替えるという考え方です。
　　0～4の5つの数値を使うことで、4種類のジャケット+脱ぎ状態の5種類の状態を切り替えることが出来ます。

　色々言ってますが、実のところ想定通り動く作り方が正解です。
　作り方は色々あります。