トマシープが学ぶ

Unity/VR/AR/デザイン好きのミーハー 記事内容は自分用のメモです

【Unity】VRMモデルの表情をコントローラーで変える【VRTK】

VRアプリ内でVRoidモデルの表情を変えたい

操作系

ほかのVRアプリではどんな操作で表情を変えているのか。

VirtualCast

右手コントローラーのトラックパッド・スティックで変更

f:id:bibinbaleo:20200622160102p:plain

VRchat

VRChatもタッチパッド

表情切替操作

 

VRMのBlendShapeスクリプト

VRMのBlendShapeをスクリプトから制御するには?

公式ドキュメント。

vrm.dev

var proxy=GetComponent<VRMBlendShapeProxy>();

// enumで呼び出し
proxy.ImmediatelySetValue(BlendShapePreset.A, 1.0f); // 0から1で指定

// stringで呼び出し
proxy.ImmediatelySetValue("A", 1.0f);

 

注意

・ImmediatelySetValueを使う。過去の記事で出てくるSetValueは旧式だって。

・enumにないもの(unknown)はstringで呼び出す。

・<VRMBlendShapeProxy>はupdateでGetしないと取れないらしい。

qiita.com

prince9.hatenablog.com

クラス

これらの記事を参考にクラス作ってみた。

        public void SetBlendShape(VRM.BlendShapePreset preset)
        {
            proxy.ImmediatelySetValue(preset, 1f);
        }
        public void ResetBlendShape(VRM.BlendShapePreset preset)
        {
            proxy.ImmediatelySetValue(preset, 0f);
        }

 

こんな感じで呼び出す

SetBlendShape(BlendShapePreset.Sorrow);

でもこれだとBlendShapePresetに登録されていないもの(unknown)が呼び出せないことに気づいた。string呼び出しもできるようにせねば・・・

Dictionary

こんな感じにしてみた

        private Dictionary<string, BlendShapeKey> _BlendShapeMap = new Dictionary<string, BlendShapeKey>()
        {
            { "Neutral", new BlendShapeKey(BlendShapePreset.Neutral ) },
            { "Fun", new BlendShapeKey(BlendShapePreset.Fun ) },
            { "Zitome", new BlendShapeKey(BlendShapePreset.Sorrow ) },
            { "Wink", new BlendShapeKey(BlendShapePreset.Blink_L ) },
            { "Surprised", new BlendShapeKey("Surprised" ) },

        };
~~
        private void SetBlendShape(string key)
        {          
            proxy.ImmediatelySetValue(_BlendShapeMap[key], 1f);
        }

///BlendShapeをすべて0にする private void ResetBlendShape() { foreach (KeyValuePair<string, BlendShapeKey> pair in _BlendShapeMap) { if (proxy.GetValue(pair.Value) > 0) { proxy.ImmediatelySetValue(pair.Value, 0f); } } }

 

もっといい方法がありそうだけどとりあえずこれで動く

SetBlendShape("Surprised")

SetBlendShape("Zitome")

みたいに呼び出せばよい。

 

表情をすべて0に戻すときはResetBlendShape()を呼ぶ。

他の表情を呼び出したときに、前の表情を0に戻すなら、SetBlendShape()の中にResetBlendShape()を置く。

 

表情切り替えのトリガー

他のアプリを習って、タッチパッドの向きで表情を変えたい。

RadialMenu

VRTKについているRadialMenuというのを使えば行けるか?

negi-lab.blog.jp

RadialMenuを検索で探す

f:id:bibinbaleo:20200622172029p:plain

プレハブを各手のScriptAreaの下に置く

f:id:bibinbaleo:20200622171904p:plain

f:id:bibinbaleo:20200622171907p:plain

PanelにVRTK_RadialMenuがついている。

f:id:bibinbaleo:20200622171911p:plain

そこのButtonを開くと、Buttonの数やアイコン、クリックしたときの動作を設定できる。

f:id:bibinbaleo:20200622171914p:plain

イベント

Clickはスティックを傾けたうえで、押し込んだ時に反応する。

 

Hoverで proxy.ImmediatelySetValue(preset, 1f);

Hover Exitでproxy.ImmediatelySetValue(preset, 0f);

するのが良いのか・・・?と思ったが、なんかどれもうまくいかなかった。一瞬で表情が消えたりする。

メニューの見た目

アイコンはButtons>Element>ButtonIcon

f:id:bibinbaleo:20200624133839p:plain

背景の色はButtonColorで変える

f:id:bibinbaleo:20200624133834p:plain

変更は、一番下のRegenerate Buttonsを押さないと反映されない

f:id:bibinbaleo:20200624133837p:plain

自分で実装

メニュー表示部分はRadialMenuをそのまま使った。ニュってメニューが出てくるの面白い。

 

いろいろあって、自分でタッチパッドの押下を自分のスクリプトで取得して実装することにした。それは別記事にイベントの取り方を書いたので、こちらを見てください。良いやり方かは分からない。

bibinbaleo.hatenablog.com

 

表情アイコン

MaterialDesign

f:id:bibinbaleo:20200625170809p:plain

Icons - Material Design

こちらのサイトもよかった。

iconbox.fun

f:id:bibinbaleo:20200625170910p:plain

BlendShapeの設定

ここをみよ。

vrm.dev

VRoidモデルの表情は独特だから、少しパラメーターをいじって、口の大きさとか゚減らしたほうがいいかも

リップシンク

声によってリップシンクしている時に表情変えたらどうなるんだろう?

 

最後に

もっとクールな方法ありそう・・・