Radial PuppetとFloat変数で無段階変化を実装する
今回はFloat変数とRadial Puppetについて解説していきます。
Expression Menuの解説のときに割愛したところ、需要があったみたいなので若干罪悪感があります。
Int型やBool型での操作はある程度理解している前提で、差異を中心に説明していきます。
Avatars 3.0でのAnimation設定自体に自信がない場合は適宜こちらをご参照ください。
想定読者
- Avatars 3.0のExpressions Menuの使い方はわかる
Contents
そもそも何ができるの?
Float変数は、0から1の間の少数で取ることのできる変数です。
これをRadial Puppet方式で制御することで、無段階のAnimation制御が可能になります。
例えば何ができるの?というと、
- 小物の大きさを変える
- 髪色を徐々に変える
- パーティクルの放出量を調節する
などなどです。
販売アバターだと、髪の長さや胸の大きさのシェイプキー調整に設定されていることが多いですね。
あとは、長物武器の持つ部分を変えたり、目の閉じ具合を制御したりなど……
ちなみに、FloatをAnimation Controller内で使う方法は大きく2種類あります。
Motion Time方式と、Blendtree方式です。
単純な変化なら前者がわかりやすいと思うので、今回はMotion Timeの説明をしていきます。
Animationを作る
まずはAnimationを作っていきます。
Float変数を利用する場合は、Animationもそれ用の特殊な(?)形を作っておく必要があります。
完成形はこんな感じです。


0フレーム目と1フレーム目を両極端の値にします。
フレーム数は任意ですが、あまりに少ないとガタつく懸念があるのである程度大きくするのを推奨します。
(画像では60フレーム。これで困ったことはないですが100くらいあってもいいのかも)
Unityは勝手に間のフレームの値を補完してくれるので、これで徐々に大きくなるAnimationができました。
念のため、Previewや再生ヘッドの移動などで確認してみてください。
Animationの変化の割合を一定にする(任意)
勝手に間の値を補完してくれるUnityですが、そのままだと変化の割合が一定ではありません。
先ほど作ったAnimationのCurveのタブを開いてみます。

緩やかに変化し始めて加速し、また緩やかに停止するという曲線になっているのがわかります。
別にこのままでも大した問題はありませんし、ものによってはこの方が望ましいかもしれません。
ただ、気になる人のためにここの設定も紹介しておきます。

キーフレームを選択して右クリック、Both TangentsをLinearにします。
終端側のフレームも同様に操作します。

これで、直線的に変化するようになりました。
また、Constantを設定すると補完を行わない(突然変化する)設定も可能です。

値が1.0になったときだけ大きくなるという設定になりますね。
上の例だとまるで意味がない(IntどころかBoolでもいい)のですが、キーフレームを複数打つと効果的な場合があります。
これは最後におまけの応用で説明します。
Animation Controllerの設定をする
Animationができたら、Controller側の設定をしていきます。
下準備として、まずはParameter自体を定義しなくてはなりません。
アバターで使っているParameterの一覧に、任意の名前のFloat変数を追加します。

Animation Controller側でも忘れずに定義しておきます。
右上の+マークからFloatです。

次に、レイヤーの設定をします。
適当なレイヤーを追加して、そこに先ほどのAnimationを配置します。
レイヤーのウェイト設定忘れなどには気を付けましょう
画像ではちょっと別の設定をしているのでTransitionが引かれていますが(ワールド固定中だけ大きさが可変)、
デフォルトのオレンジ色のStateに先ほどのAnimationを割り当てて構いません。

Motion TimeのParameterにチェックを入れて、先ほど追加したFloat変数を指定します。
このStateにいる間、指定したFloatの値に従ってAnimationが再生されます。
0であれば最初のフレーム、0.5であれば真ん中、1なら最後のフレームといった感じです。
Expressions MenuにRadial Puppetを追加する
仕上げに、Expressions MenuでFloatの値を制御できるようにします。
Expressions MenuのAdd Controlからこのような感じで設定します。

Parameters Rotationがこのメニューで制御できる変数です。
上の紛らわしいParameterという項目は、このメニューを開いている間に設定される変数と値です。
これはこれで別のParameterを設定しておくのもありです。
手元で大きさを変えている間、リンゴが光り輝くとか……?
ちなみに同じ設定がさりげなくSubmenuにもあります。
これで設定は完了です。
実際にVRChatで試してみましょう。


応用おまけ:Constantを利用する例
最後におまけとして、複数キーフレームを打ってRadial Puppetを使う例を紹介してみます。
完成図はこんな感じです。

何をやっているかというと、マテリアルのUVスクロールの値を変化させて瓶のラベルを変えています。
スクロールの途中が見えては困るので、特定の値になったら瞬間的に変化する設定にしています。
有限のラベル数なのでIntで事足りるのも確かなのですが、
Radial Puppetにすることで1つのメニューに8つの状態を内包することができます。
あまりメニューやレイヤーが散らかるよりはと思いこのような設定にしてみました。
ちなみに、VRChatのアバターには128コストまでのパラメータを追加定義することができ、
IntとFloatのコストは同じ8です(Boolは1)。
なので、IntとFloatで得られる結果が同じであれば好みの方を使うといいと思います。