[Unity+Live2D]再生する音に合わせてリップシンクする

# はじめに
Live2Dモデルが再生する音に合わせてリップシンクする方法をまとめてみました。

リップシンクの設定をする前に今回のリップシンクする対象のモデルを以下の手順で配置します。
[Unity初心者がUnityでLive2Dモデルを動かすため環境構築をした](https://qiita.com/nori0__/items/988dcd7b038c838ca851)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/9f843f4b-3618-3da0-e256-60ced18de565.png)
口元がよく見えた方がいいので、Main CameraのSizeは0.7くらいがいいかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/12cbb36b-e7c4-b0bb-33dd-2119e140eb8e.png)


## 起動時に音声を再生しリップシンクする
公式の[Cubism SDK Tutorial リップシンクの設定](https://docs.live2d.com/cubism-sdk-tutorials/lipsync/)の手順を実施し、起動時に再生した音声に対してリップシンクするように設定します。

1.リップシンクを管理するコンポーネントをアタッチ
モデルのインスタンスにCubismMouthControllerをアタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/7a2b3d8b-1425-ab0c-0962-b4cee51182c1.png)

[Cubism SDK Tutorial リップシンクの設定](https://docs.live2d.com/cubism-sdk-tutorials/lipsync/) より、設定項目は以下の指定をする必要があります。
>CubismMouthControllerには、設定項目が2つあります。
– Blend Mode：指定のパラメータに現在設定されている値に対して、Mouth Openingの値をどう計算するのかを指定します。
Mutiply：現在設定されている値にMouth Openingの値を掛け合わせます。
Additive：現在設定されている値にMouth Openingの値を足し合わせます。
Override：現在設定されている値をMouth Openingの値で上書きします。
– Mouth Opening：口の開閉の値です。1で開いた状態、0で閉じた状態として扱います。この値が外から操作されると、指定されたパラメータの値も連動します。

Blend ModeをOrverrideにします。

2.リップシンクをさせるパラメータを指定
モデルのインスタンスのParamMouthOpenYに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/4d701fff-094f-ff43-4728-7f250659c0a9.png)
CubismMouthParameterをアタッチします。
これで、CubismMouthControllerでParamMouthOpenYが扱われるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/59c977d9-5841-7afa-9051-5e53c1a2c0ce.png)

3.指定されたパラメータの値を操作するコンポーネントを設定
モデルのインスタンスに自動リップシンクするためにリップシンクの入力用コンポーネントとしてCubismAudioMouthInputをアタッチします。
CubismAudioMouthInputはAudio Souceの音量でCubismMouthControllerのMouth Openingの値を操作しているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/fc88ff4a-ce6a-6314-d738-dbb3f6d6afdc.png)

[Cubism SDK Tutorial リップシンクの設定](https://docs.live2d.com/cubism-sdk-tutorials/lipsync/) より、設定項目は以下の指定をする必要があります。
>CubismAudioMouthInputには、以下の4つの設定項目があります。
- Audio Input：入力に使用するAudioSourceを設定します。ここで設定したAudioSourceにセットされたAudioClipの音量を使用します。
- Sampling Quality：サンプリングする音量の精度を設定します。以下の設定の並びが下になるほど精度が上がりますが、計算の負荷も上がります。
- High
- Very High
- Maximum
- Gain：サンプリングした音量を、何倍した値で扱うかを設定します。1で等倍です。
- Smoothing：音量から算出する開閉の値をどのくらいスムージングするかを設定します。値を大きくするほど滑らかになりますが、計算の負荷も上がります。

今回はGainを10、Smoothingを1にします。
Gainを小さくすると、口を開く大きさが小さくなります。
Smoothingを小さくすると、口の開閉の動きが緩やかになります。
リップシンクの動きを大きく滑らかにして見てみたいので、最大値を入れます。
([Cubism SDK Tutorial リップシンクの設定](https://docs.live2d.com/cubism-sdk-tutorials/lipsync/)では、Gainが1になっていますが、1だとほとんど開閉しません)

CubismAudioMouthInputのAudio ImputにAudio Sourceを入れるとリップシンクしてくれるようになりますので、まずAudio Sourceを作りましょう。
Hierarchyタブで右クリックして、Audio Sourceを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/28f26557-b1bb-f9d8-cd32-0c1ba6395f69.png)

Play On Awakeにチェックがついていれば起動時に音声ファイルが再生されます。
今回は起動時にリップシンクするところが見たいので、チェックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/e5cf73fa-2f8f-a30f-1097-8682db85d80f.png)

Audio Clipには音声ファイルを置きます。
音声ファイルはProjectにドラッグアンドドロップで置きます。
Unityで使える拡張子は[オーディオファイル - Unityマニュアル](https://docs.unity3d.com/ja/2019.3/Manual/AudioFiles.html)に記載があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/5636fed3-fb9f-f61e-b2e9-dae1587ae730.png)

作ったAudio SourceはCubismAudioMouthInputのAudio Imputへ設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/263d9ab5-4c8e-05fc-93f3-7ea955a26a73.png)

Playボタンを押してリップシンクするか見てみましょう。
音量に応じて口の開閉の大きさが変わると思います。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">サンプルモデルがリップシンクする <a href="https://t.co/V0iejDzxjp">pic.twitter.com/V0iejDzxjp</a></p>&mdash; nori (@nori0__) <a href="https://twitter.com/nori0__/status/1218836008919162880?ref_src=twsrc%5Etfw">January 19, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## キー操作で再生される音声を変える
上記の操作だと決まった音声ファイルしか再生できないので、いろいろなファイルが再生できるようにしてみました。
C#スクリプトでAudio SourceのAudioClipを変更するようにします。

ProjectタブにC#スクリプトをAudioControllerという名前で新規追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/a44beba7-a442-5b98-c5ae-ad2a020aa6d0.png)

C#スクリプトをダブルクリックしてエディターで編集します。

```csharp
using Live2D.Cubism.Framework.MouthMovement;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioController : MonoBehaviour
{
    [SerializeField]
    CubismAudioMouthInput audioMouthInput;

    public AudioClip AudioClip1;
    public AudioClip AudioClip2;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.Z))
        {
            // Zが押された時、AudioClip1を再生する
            playAudio(AudioClip1, stopAudio);
        }
        else if (Input.GetKey(KeyCode.Y))
        {
            // Yが押された時、AudioClip2を再生する
            playAudio(AudioClip2, stopAudio);
        }
    }

    public delegate void functionType();
    private IEnumerator Checking(functionType callback)
    {
        if (audioMouthInput?.AudioInput == null)
        {
            Debug.LogError("audioMouthInput.AudioInput no set");
            yield return null;
        }

        while (true)
        {
            // 1フレーム待つ
            yield return new WaitForFixedUpdate();

            if (!audioMouthInput.AudioInput.isPlaying)
            {
                callback();
                break;
            }
        }
    }

    private void playAudio(AudioClip audioClip, functionType callback)
    {
        if (audioMouthInput?.AudioInput == null)
        {
            Debug.LogError("audioMouthInput.AudioInput設定なし");
            return;
        }

        audioMouthInput.AudioInput.clip = audioClip; // 音声ファイルを変更
        audioMouthInput.AudioInput.Play();
        StartCoroutine(Checking(callback));
        Debug.Log("play sound");
    }

    // Checkingメソッドのcallbackメソッドで実行される
    private void stopAudio()
    {
        Debug.Log("stop sound");
    }
}

```

MainシーンにGameObjectを作成して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/4a7fcec4-a48e-44a0-c217-760b10f78b86.png)
GameObjectにC#スクリプトを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/8b6bb229-7cf5-8844-1de8-58d70b41b1e8.png)

GameObjectにフィールドを設定します。
Audio Mouth Inputにモデルのインスタンスを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/720fd070-f89d-d646-9e9d-ad5900f7b406.png)

上記で記載した手順[「起動時に音声を再生しリップシンクする」](https://qiita.com/nori0__/items/4936a13602812cbf3cf5#%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E9%9F%B3%E5%A3%B0%E3%82%92%E5%86%8D%E7%94%9F%E3%81%97%E3%83%AA%E3%83%83%E3%83%97%E3%82%B7%E3%83%B3%E3%82%AF%E3%81%99%E3%82%8B)でモデルのインスタンスにCubismAudioMouthInputをアタッチしていたら選べると思います。

Audio Clip1、Audio Clip2に音声ファイルを設定します。
Projectタブに音声ファイルを置いたものをドラッグアンドドロップしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/fc58f42a-0874-19b6-eec6-22cc8aef42b0.png)

Playボタンを押して、Zを押すとAudio Clip1に設定した音声ファイルが、Yを押すとAudio Clip2に設定した音声ファイルが再生されます。

## 参考
https://qiita.com/TakashiHamada/items/a5ff15ca7e63c06bfb23