VRM.BlendShapeProxy
v0.58
BlendShapeKeyのインタフェースを厳格化、整理
BlendShapeKeyを作成する方法が不明瞭だったため、 より明示的な API に置き換えました。
- BlendShapeClip.Key 追加
arguments | before | after | 備考 |
---|---|---|---|
string name, BlendShapePreset preset | public constructor | private constructor | BlendShapePreset.Unknownのときの挙動が不明瞭だった。代わりに、CreateFromPreset または CreateUnknown を使用してください |
BlendShapeClip | BlendShapeKey.CreateFrom | BlendShapeKey.CreateFromClip | 他の関数に合わせて、名前を変更 |
BlendShapePreset | public constructor | BlendShapeKey.CreateFromPreset | オーバーロードをやめて明示的な関数に変更 |
string | public constructor | BlendShapeKey.CreateUnknown | オーバーロードをやめて明示的な関数に変更。 |
使用するメソッド
- [推奨]
SetValues
- [非推奨]
ImmediatelySetValue
- [上級者向け]
AccumulateValue
- [上級者向け]
Apply
スクリプトから BlendShape weight を適用する
SetValues
関数のみを使用します。
そのフレームで必要な表情の weight 値をすべて集めてから SetValues
を 1 回だけ呼んで設定します。
var proxy = GetComponent<VRMBlendShapeProxy>();
proxy.SetValues(new Dictionary<BlendShapeKey, float>
{
{BlendShapeKey.CreateFromPreset(BlendShapePreset.A), 1f}, // [0, 1] の範囲で Weight を指定
{BlendShapeKey.CreateFromPreset(BlendShapePreset.Joy), 1f}, // システム定義の表情は enum で指定
{BlendShapeKey.CreateUnknown("USER_DEFINED_FACIAL"), 1f}, // ユーザ定義の表情は string で指定
});
複数の BlendShape weight を適用する際の競合の問題について
この節では、なぜ SetValues
を使わなければならないのかという疑問に回答します。
たとえば 2 つの VRMBlendShape Blink_L
と Blink_R
が
VRMBlendShape Blink_L
- Mesh
A
の Blendshapeeye_close_L
の weight 値100
- Mesh
A
の Blendshapeeye_close_R
の weight 値1
VRMBlendShape Blink_R
- Mesh
A
の Blendshapeeye_close_L
の weight 値1
- Mesh
A
の Blendshapeeye_close_R
の weight 値100
で定義されているとします。 このとき両目を閉じたいモチベーションから、両方を有効にする意図で下記のように実行します。
proxy.ImmediatelySetValue(BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_L), 1.0f);
proxy.ImmediatelySetValue(BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_R), 1.0f);
すると、左目だけが開いてしまいます。
これは後から ImmediateSetValue
した Blink_R
が Blink_L
と競合して weight を上書きしてしまうからです。
したがって VRM の表情制御においては下記の 2 通りのどちらかの方法で書くことが求められます。
これらの方法はこの競合の問題を解決して表情を設定することができます。
proxy.SetValues(new Dictionary<BlendShapeKey, float>
{
{BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_L), 1.0f},
{BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_R), 1.0f},
});