アバターを自動でまばたきさせる


こんにちは!八ツ橋まろんですっ!

こちらの記事で、Animatorを使ったアバターのハンドサイン、リップシンク、まばたき、表情遷移ついて解説しています。
https://qiita.com/Maron_Vtuber/items/2dca46dfd454588e15d3

本記事はその中の「自動まばたきをさせるスクリプト」について書きます。

本記事に必要な最少限のAnimatorの知識の概要を以下に説明します。

AnimatorにはLayer機能があり、ベースとなるアニメーションに対してアニメーションを上書き・ブレンドすることができ、その度合いはWeightという変数でコントロールできます。今回は"まばたき"なので、ベースのアニメーションは"目を開いた状態"とし、Layer機能で"目を閉じた状態"のアニメーションを上書きします。

ここからは、上の記事でAnimatorの設定は終わっているものとして進めていきます。
(=必要なAnimatorのLayer設定が終わっていて、目を開いた状態と閉じた状態のアニメーションが作成済み)

完成したスクリプトでのインスペクタを見てみます。

・このスクリプトによって、指定したAnimatorのLayerのWeightを操作して、一定周期でループするまばたきをします。
・待ち時間→1パチ→待ち時間→1パチ→待ち時間→2パチ→を繰り返します。
・上の画像では、CubeのAnimatorのLayer 1のウェイトを操作します
・上の画像では、3秒待ち→1パチ→5秒待ち→1パチ→7秒待ち→2パチ→ループ となります。
・また、目を閉じきってから開き始めるまでの時間は0.1secです。

Layerの数え方は以下の通りです

コードは以下のようになっています。

AutoBlink.cs
using UnityEngine;
using System.Collections;

/// <summary>
/// 自動瞬きを行うクラス。
/// 使用するには適切に設定されたAnimatorControllerをもつ
/// オブジェクトを_Animatorに指定する必要がある。
/// </summary>

public class AutoBlink : MonoBehaviour
{
    float weight = 0f;
    float velocity = 0.0f;
    bool isBlink = false;

    [SerializeField]
    float OnceBlinkTime_1 = 3f;
    [SerializeField]
    float OnceBlinkTime_2 = 5f;
    [SerializeField]
    float TwiceBlinkTime_3 = 7f;
    [SerializeField]
    float CloseTime = 0.1f;
    [SerializeField]
    Animator _Animator;

    [SerializeField]
    int Layer = 3; 
    // ↑↑↑↑_AnimatorのLayer番号
    // VR Motion Recorderでは3番がまばたき用のLayerとなっている
    // (0, 1, 2, 3, ...と数えるから、実際は4番目のLayer)
    // 扱う_Animatorによって適切に設定すること
    // AnimatorのLayer機能については前の記事(冒頭に紹介した記事)を参照のこと

    void Start()
    {
        // まばたきループ開始
        StartCoroutine("AutoBlinkCoroutine");
    }

    // _Animatorのweightを毎フレーム更新する
    private void Update()
    {
        if (isBlink)
        {
            // isBlink = trueならweightを1にもっていく
            // 0.05secかけてweightを1にする
            weight = Mathf.SmoothDamp(weight, 1, ref velocity, 0.05f);
        }
        else
        {
            // isBlink = falseならweightを0にもっていく
            // 0.05secかけてweightを0にする
            weight = Mathf.SmoothDamp(weight, 0, ref velocity, 0.05f);
        }
        // AnimatorのLayerのウェイトを更新
        _Animator.SetLayerWeight(Layer, weight);
    }

    //「コルーチン」で呼び出すメソッド
    IEnumerator AutoBlinkCoroutine()
    {
        //無限ループ
        while (true)
        {
            //まばたき1回目。単発でまばたきをする。
            yield return new WaitForSeconds(OnceBlinkTime_1);
            isBlink = true;
            yield return new WaitForSeconds(CloseTime);
            isBlink = false;

            //まばたき2回目。単発でまばたきをする。
            yield return new WaitForSeconds(OnceBlinkTime_2);
            isBlink = true;
            yield return new WaitForSeconds(CloseTime);
            isBlink = false;

            //まばたき3回目。ここでは2回連続でまばたきをする。
            yield return new WaitForSeconds(TwiceBlinkTime_3);
            isBlink = true;
            yield return new WaitForSeconds(CloseTime);
            isBlink = false;
            yield return new WaitForSeconds(CloseTime);
            isBlink = true;
            yield return new WaitForSeconds(CloseTime);
            isBlink = false;
        }
    }
}

一定時間を待つのにコルーチンを使っています。

IEnumerator AutoBlinkCoroutine()
{
   [やりたい処理を入れる]
}

コルーチンは以下の命令で開始します。

StartCoroutine("AutoBlinkCoroutine");

コルーチン内で以下を書くと「一定時間待つ」ことができます。

yield return new WaitForSeconds(OnceBlinkTime_1);

また、まばたきのウェイト計算に使っている

Mathf.SmoothDamp(A,B,C,D);

の関数はとても便利です。気になったら調べると良いかも。

Vtuberはまばたきがない場合、実在感に少し欠けますが、まばたきをする場合、現実のまばたきとリンクする必要はなく、
このスクリプトのように3秒、5秒、7秒周期でまばたきをさせるだけで違和感のない動きになり、実在感が増します。
Vtuberには是非まばたきを実装してあげてください!

以上、「アバターを自動でまばたきさせる」でしたっ

八ツ橋まろん

🌟🌟🌟こちらも覗いてみてねっ🌟🌟🌟
Twitter
https://twitter.com/Maron_Vtuber
pixivFANBOX (ツールの配布)
https://www.pixiv.net/fanbox/creator/16717003
Youtube (ツールの解説やVtuber活動)
https://www.youtube.com/channel/UCiIbLpncjzahHsp8cokG56g