この記事ではVRM1.0の表情操作について詳述します。表情を操作するスクリプトの書き方や、VRM1.0の新機能(表情のオーバーライドコントロール)についても言及しています。
前提:3Dモデルの表情操作
VRM1.0に入る前に、まずはUnityにおける3Dモデルの表情操作についておさらいしましょう。
Unityで扱われる3Dモデルにおける表情操作は、SkinnedMeshRendererというコンポーネントで行います。
SkinnedMeshRendererは、VRoidStudioから出力したVRMファイルの場合、ヒエラルキーにある「Face」のコンポーネントになっています。
FaceをクリックするとInspectorにSkinnedMeshRendererが出てきて、3Dモデルに固有の表情(BlendShapesといいます)がスライダーとともに一覧表示されます。
各BlendShapesのスライダーを操作すれば表情を細かく変化させることができます。もちろん、複数のBlendShapesの組み合わせも可能です。
また、数字を直接変更すればマイナス値や100超えといった限界突破も可能です。
VRM0の表情操作
VRM0は、BlendShapeProxyという表情操作機能を持っています。
あらかじめBlendShapesを組み合わせた表情をBlendShapeProxyとして登録しておくと、Unityの再生時にBlendShapeProxyを操作できます。
BlendShapeProxyは、ヒエラルキーとしてはVRMそのもののコンポーネントとなっています。
BlendShapeProxyにはBlendShapesと比べていくつかの制約があります。
- BlendShapeProxyはUnityを再生していない時には操作できません。
- BlendShapeProxyは0から1までの値しか取れず、限界突破はできません。
- VRoidStudioから出力したVRMファイルではBlendShapeProxyは一部のBlendShapesにしか設定されていないため、全てのBlendShapesをBlendShapeProxyで操作しようとするとUnityでBlendShapeProxyの追加登録作業が必要になります。
BlendShapeProxyに上記のような制約がある一方、VRM0ではSkinnedMeshRendererの操作には制約がないため、VRM0において簡単に自由な表情を表出させるにはBlendShapeProxyは使わずSkinnedMeshRendererだけを操作するのが最も楽です。
なお、BlendShapeProxyは限界突破はできないものの複数の表情設定を重ね掛けすることはできるので、ある程度複雑な表情を作れます。一方で、もともと笑っていて目が喜び閉じ状態になっているときにアプリケーションでまばたき(Blink)を重ねると変な表情になってしまうといった問題があります。
VRM1.0の表情操作
VRM1.0ではBlendShapeProxyは廃止され、新たにExpressionという表情機能が追加されました。
Expressionも複数のSkinnedMeshRendererのBlendShapesを組み合わせて設定する点はBlendShapeProxyと同じですが、Expressionでは各々の表情設定は個別にファイル化されるとともに、「プリセットの表情」と「カスタムで後から追加した表情(Custom Clips)」に分かれて扱われるようになりました。
Expressionにもいくつか制約がありますが、それ以前にVRM1.0ではSkinnedMeshRendererの操作に制約があります。
その制約は、Unityの再生中は「Expression」で使われるBlendShapesはSkinnedMeshRendererで操作できなくなるという点です。
プリセットのExpressionに使われるだけでSkinnedMeshRendererで当該表情は操作できなくなるため、VRoidStudio産のVRMをそのままVRM1.0化したモデルでは「Fcl_ALL_XXX」系と、Blink(両眼片目いずれも)、あいうえおが全て動かせなくなります。
他にもVRM1.0の表情操作には制約があります。
- ExpressionもBlendShapeProxyと同様にUnity再生中にしか操作できません。
- BlendShapeProxyはUnityエディタのスライダーで表情操作できましたが、ExpressionはUnityエディタでは表情操作ができなくなっており、スクリプトでしか操作できません。表情単体の動きをUnityエディタ上で確認する機能はありますが、複数のExpressionを組み合わせたときの挙動確認はスクリプトでないと不可能です。
一方で、ExpressionはBlendShapeProxyと違って表情パラメータの限界突破はできるようになりました。
以上をまとめると、VRM1.0で複数表情の組み合わせを実現するにはスクリプトを組む必要があります。
また、VRM0ではUnityを再生した状態でUnityエディタ上で表情を細かく調整することができましたが、VRM1.0ではそれも(中途半端に)不可能になりました。
VRM1.0の表情操作スクリプト
それではVRM1.0で表情操作するためのスクリプトは、どういったものになるのでしょうか。
その前に、SkinnedMeshRendererのBlendShapesの表情を操作するスクリプトの型を出しておきます。
GameObject.Find("Face").GetComponent<SkinnedMeshRenderer>().SetBlendShapeWeight(int index, float value);
indexはint型なので、初心者でも悩まずにスクリプトを考えられます。
これが、Expressionではこうなります。
GameObject.Find("VRM1").GetComponent<Vrm10Instance>().Runtime.Expression.SeiWeight(ExpressionKey expressionKey, float weight);
で、このExpressionKeyというのが一筋縄ではいかないのです。。
まず、初期化しなければなりません。
次に、プリセットとカスタムとで違うスクリプトになります。
また、プリセットの表情のindexを数字で扱おうとするとenum型への変換が必要です。
ちなみに、カスタムの表情を指定するキー項目は表情の名前の文字列(string型)です。
というわけで、こんなスクリプトが必要になります。
ExpressionKey expressionKey = new ExpressionKey(); if (プリセットの場合) { expressionKey = ExpressionKey.CreateFromPreset((ExpressionPreset)Enum.ToObject(typeof(ExpressionPreset), int index);} else (カスタムの場合){ expressionKey = ExpressionKey.CreateCustom(string costomKey) }
VRM1.0の新機能(表情のOverrideコントロール)
VRM1.0には、喜怒哀楽の表情とまばたき・発音(あいうえお)が重なって変な表情になるのを防ぐ機能があります。
プリセットの表情には、まばたき(Blink)、あいうえお(Mouth)、目の上下左右(LookAt)があります。以下この文章において、これら(Blink・Mouth・LookAt)の表情を「Override対象の表情」と称することにします。
今回VRM1.0で追加された機能は、ある表情がOverride対象の表情と重なったときに、Override対象の表情の方を打ち消したり(Block)、段階的に移行する(ブレンド)ように調整してくれる機能です。
表情ごとに、
- Blinkと重なったときにBlinkをブロックするか?ブレンドするか?何もしない(表情を重ね掛けする)か?
- Mouthと重なったときにMouthをブロックするか?ブレンドするか?何もしない(表情を重ね掛けする)か?
- LookAtと重なったときにLookAtをブロックするか?ブレンドするか?何もしない(表情を重ね掛けする)か?
を設定することになります。
プリセットの表情でも、カスタムの表情でも設定できます。
なお、Expressionの表情パラメータは限界突破することができますが、限界突破したらこのOverrideコントロール機能は無効になります。
もう一点、これは結構重大ですが、VRM1.0のGaze機能で視線をカメラなどに向けている場合、Overrideコントロールを効かせるとGaze機能が無効になってしまいます。
例えば、カメラ目線を指定していても、Overrideコントロールが効いた状態になると、カメラ目線が解除されて顔の真正面を見るようになります。
なお、先ほど書いたようにそもそも複数のExpressionを組み合わせたときの挙動はスクリプトを組まないと分からないので、挙動確認するだけでもなかなか手間です。。
以上、VRM1.0の表情についてでした~