【Unity】VRoidの表情をC#スクリプトから変更する方法!まばたきを実装してみよう

VRoidの表情を制御しよう ゲーム開発

今回はかなりニッチな話題なのですが、タイトルの通り

UnityでVRoidキャラクターの表情をC#スクリプトから変更する方法

をご紹介するという内容です。

VRoidは正式版になってからかなりゲームに使いやすくなったのですが、そうは言っても元々ゲーム向けという感じではないのでUnityで使おうと思うと困ることがあります。特にキャラクターの表情に関しては豊富な設定項目があるのですが、それをスクリプトから変更する方法がよくわからず頭を抱えてしまうという方もいらっしゃるのではないでしょうか。

そこでここでは、VRoidの表情をC#スクリプトから変更する方法について

  • 表情の基本的な操作方法
  • DOTweenを使って滑らかな変更を実現する方法(サンプルとしてまばたきを実装)

といった点を説明していきますね。


※なお、VRoidをUnityにインポートする方法は下記の記事で詳しく説明していますので必要な場合はそちらも併せてご覧ください。

【Unity】VRoid Studioで作ったキャラクターをUnityで動かす方法
Unityで3Dゲームを作っているとアニメ風のキャラ(特に女の子)の3Dモデルが欲しくなります。しかしアセットストアを探してもアニメ風のキャラは少なく、あってもクオリティの高いものは高額なので気軽に導入できないという状況です。 そこで私が目...

前提:そもそも、VRoidの表情はどういう仕組みになっているか

でははじめに、そもそもVRoid(つまりVRM規格のキャラクターモデル)の表情はどういう仕組みで実現されているのかを簡単に説明しておきます。

VRoidの表情の変化は「ブレンドシェイプ(Blend Shape)」という、3DCGではよく使われている仕組みを利用して実装されています。これは頂点数が同じ3Dモデルにおいて異なる形状を複数記録しておき、それらをブレンドすることで滑らかに形をアニメーションさせることができるというものです。

それで通常はC#スクリプトから直接Skinned Mesh Rendererにアクセスしてブレンドシェイプの操作を行うのですが、VRoidの場合は複雑な表情を表現できるようにブレンドシェイプの数が非常に多いのでユーザーがそのまま表情をいじろうと思うと面倒です。そこでVRoidには「Blend Shape Proxy」というスクリプトが用意されていて、例えば予め用意されている表情の中から目的の表情を指定して変化させる、といった具合に比較的簡単に表情を操作できるようになっています。

C#スクリプトから表情を変更する方法

ただしBlend Shape Proxyの使い方が少し分かりづらいので、まずはこのスクリプトの使い方を説明します。結論から言うと基本的には次の関数を使って表情を変化させます。

  1. AccumlateValue関数&Apply関数
  2. ImmediatelySetValue関数

それぞれ詳しく見ていきましょう。

AccumlateValue関数&Apply関数

一つ目は表情の変化をストックするAccumlateValue関数と、それを適用するApply関数です。複数の表情を重ねておき、任意のタイミングで変化させたいときに使います。

proxy.AccumulateValue(key, value);
proxy.Apply();

なおproxyはBlend Shape Proxy、keyはBlendShapeKey型の引数、valueはfloat型の引数です。BlendShapeKeyは次のようにCreateFromPreset関数で表情プリセットから取得することも可能です。

BlendShapeKey.CreateFromPreset(preset);

ImmediatelySetValue関数

二つ目は表情を即座に変更するImmediatelySetValue関数です。基本的には先ほどのAccumlateValue関数を使えばOKだと思いますが、必要に応じてこちらもご活用ください。

proxy.ImmediatelySetValue(key, value);

DOTweenを使って滑らかに表情を変化させてみよう

さて表情の基本的な変更方法はこんなところですが、単純に上記の関数を使うだけだと表情が一瞬で切り替わってしまうのであまり自然ではありません。

そこでここでは、DOTweenというアセットを使って滑らかに表情を変化させる方法をご紹介します。DOTweenについては以下の記事で詳しく説明しているのでそちらも併せてご覧ください。

【Unityアセット】DOTweenの使い方完全ガイド!超人気アセットを使いこなそう
今回はUnityユーザーの皆さんならおそらくご存じの神アセット「DOTween」の使い方を丁寧にご紹介するという内容です。 DOTweenは非常に人気が高いアセットなので既に持っていらっしゃる方も多いかと思いますが、正直なところ「使い方がよ...

サンプル:VRoidを滑らかにまばたきさせる

今回はサンプルとして次のような滑らかなまばたきを実装するためのC#スクリプトを掲載します。

VRoidのまばたきの例

(画像クリックでGIF再生)

このサンプルは次の2つのクラスで構成されています。

  1. FaceController
  2. AutoBlink

それぞれ詳しく見ていきましょう。

FaceController

まずは表情を滑らかに変更するためのスクリプトです。

using UnityEngine;
using VRM;
using DG.Tweening;

namespace KurokumaSoft
{

    public sealed class FaceController : MonoBehaviour
    {

        [SerializeField]
        VRMBlendShapeProxy proxy;

        bool isBusy = false;
        BlendShapePreset currentPreset;

        void Start()
        {
            InitFace(0);
        }

        public void InitFace(float duration)
        {
            ChangeFace(BlendShapePreset.Neutral, 0, 1, duration);
        }

        public void ChangeFace(BlendShapePreset preset, float startValue, float endValue, float duration, Ease ease = Ease.InOutQuad)
        {
            if (isBusy)
            {
                return;
            }

            isBusy = true;

            startValue = Mathf.Clamp01(startValue);
            endValue = Mathf.Clamp01(endValue);

            UpdateFace(currentPreset, 0);

            float progress = startValue;
            DOTween.To(() => progress, x => progress = x, endValue, duration).OnUpdate(() => { UpdateFace(preset, progress); isBusy = false; }).SetEase(ease);

            currentPreset = preset;
        }

        void UpdateFace(BlendShapePreset nextPreset, float progress)
        {
            proxy.AccumulateValue(BlendShapeKey.CreateFromPreset(nextPreset), progress);
            proxy.Apply();
        }

    }

}

ChangeFace関数がメインです。DOTween.To関数を使って、指定した秒数をかけて指定した表情に滑らかに変化させるという処理内容になっています。To関数の使い方が分からないと理解が難しいコードになっていると思うので、よく分からない方は先ほどのDOTweenの解説記事を参考になさってください。

AutoBlink

二つ目は自動的にまばたきを行うスクリプトです。

using System.Collections;
using UnityEngine;

namespace KurokumaSoft
{

    public sealed class AutoBlink : MonoBehaviour
    {

        [SerializeField]
        FaceController faceController;
        [SerializeField, Min(0)]
        float blinkDuration = 0.1f;
        [SerializeField, Min(0)]
        float blinkInterval = 3;

        bool blinking = false;
        WaitForSeconds blinkDurationWait;
        WaitForSeconds blinkIntervalWait;

        public bool IsActive { get; set; } = true;

        void Start()
        {
            blinkDurationWait = new WaitForSeconds(blinkDuration);
            blinkIntervalWait = new WaitForSeconds(blinkInterval);
        }

        void Update()
        {
            if (!IsActive)
            {
                return;
            }

            Blink();
        }

        public void Blink()
        {
            if (blinking)
            {
                return;
            }

            StartCoroutine(nameof(BlinkTimer));
        }

        IEnumerator BlinkTimer()
        {
            blinking = true;

            faceController.ChangeFace(VRM.BlendShapePreset.Blink, 0, 1, blinkDuration);
            yield return blinkDurationWait;
            yield return null;
            faceController.InitFace(blinkDuration);
            yield return blinkDurationWait;

            yield return blinkIntervalWait;

            blinking = false;
        }

    }

}

こちらはコルーチンを使って一定時間ごとに先ほどのChangeFace関数を呼び出しているだけです。

おわりに

以上、VRoidの表情をC#スクリプトから変更する方法をご紹介しました。

表情を自在に操作できるようになるとキャラクターがより一層生き生きとしてくるのでとても楽しいです。ぜひ今回の内容を参考にしていただき、魅力的なキャラクターづくりをして頂ければと思います。

この記事がUnityでのゲーム開発のお役に立てば幸いです。