MouthMovement
最終更新: 2020年1月30日
概要
MouthMovementは、リップシンク用パラメータの現在の値に対して開閉状態の値を適用する機能です。
モーションに設定されたリップシンク用のカーブや再生している音声ファイルからリアルタイムにサンプリングした値などをモデルに適用することが可能です。
モデルにリップシンクのパラメータを設定する方法については こちら をご覧ください。
MouthMovementで設定するものは口の開閉状態のみです。
口の形状を母音に合わせるというような操作をすることはできません。
Unity上でリップシンク用のパラメータを指定するには、Cubismエディタでモデルに設定しておく他、Unity上でユーザが任意に指定することができます。
Cubism SDK for Unity におけるMouthMovementは3種類の要素によって構成されています。
- パラメータ指定用のコンポーネント
- 各パラメータに値を適用するコンポーネント
- 2で適用する値の操作
1. パラメータ指定用のコンポーネント
MouthMovementに使用するパラメータを指定するには、CubismMouthParameterを使用します。
CubismMouthParameterはMonoBehaviourを継承したコンポーネントで、
[Prefabのルート]/Parameters/ 以下に配置されたGameObjectにアタッチして使用します。
これがアタッチされたGameObjectと同じIDのパラメータをリップシンク用のパラメータとして扱います。
モデル自体にリップシンク用のパラメータが設定されている場合、インポートの際にそのパラメータのGameObjectにCubismMouthParameterがアタッチされます。
CubismMouthParameterは参照先を取得するためのマーカーとして使用しているので、内部では何も処理を行っておらず、データも持っていません。
2. 各パラメータに値を適用するコンポーネント
各パラメータに開閉の値を適用するには、CubismMouthControllerを使用します。
これはMonoBehaviourを継承したコンポーネントで、使用する際はCubismのPrefabのルートにアタッチします。
初期化時に、PrefabにアタッチされたすべてのCubismMouthParameterの参照を取得します。
実行中にまばたき用のパラメータを追加/削除した場合、CubismMouthController.Refresh()を呼んで参照を取得し直します。
/// <summary> /// Refreshes controller. Call this method after adding and/or removing <see cref="CubismMouthParameter"/>s. /// </summary> public void Refresh() { var model = this.FindCubismModel(); // Fail silently... if (model == null) { return; } // Cache destinations. var tags = model .Parameters .GetComponentsMany<CubismMouthParameter>(); Destinations = new CubismParameter[tags.Length]; for (var i = 0; i < tags.Length; ++i) { Destinations[i] = tags[i].GetComponent<CubismParameter>(); } // Get cubism update controller. HasUpdateController = (GetComponent<CubismUpdateController>() != null); } ... /// <summary> /// Called by Unity. Makes sure cache is initialized. /// </summary> private void Start() { // Initialize cache. Refresh(); }
CubismMouthControllerは、毎フレームのLateUpdate()のタイミングで、CubismMouthParameterでマーキングされたパラメータに対してCubismMouthController.MouthOpeningの値を適用します。
/// <summary> /// Called by cubism update controller. Updates controller. /// </summary> /// <remarks> /// Make sure this method is called after any animations are evaluated. /// </remarks> public void OnLateUpdate() { // Fail silently. if (!enabled || Destinations == null) { return; } // Apply value. Destinations.BlendToValue(BlendMode, MouthOpening); }
MouthOpeningに設定する値は0.0f~1.0fの範囲です。
CubismMouthControllerはこの値を対象のパラメータに対して、CubismMouthController.BlendModeで設定された計算方式で適用します。
このMouthOpeningの値を外から操作することで、モデルの口を開閉させることができます。
/// <summary> /// The opening of the mouth. /// </summary> [SerializeField, Range(0f, 1f)] public float MouthOpening = 1f;
3. 2で適用する値の操作
「2. 各パラメータに値を適用するコンポーネント」で説明した通り、CubismMouthController.MouthOpeningの値を操作することで、リップシンク用のパラメータに値を適用できます。
Cubism SDK for Unity には、以下の3種類の方法でこの値を操作することができます。
- モーションによって値を操作
- 周期的に値を操作
- AudioClipからサンプリングして値を操作
また、ユーザ側でこの値を操作する処理を実装していただくことで、リップシンクの速度やタイミング等を独自にカスタマイズすることができます。
Tips
CubismMouthController.MouthOpeningを操作するコンポーネントの実行順がCubismMouthControllerよりも後である場合、意図した動作にならない可能性があります。
もし動作に問題が生じた、ユーザ側で明示的にコンポーネントの実行順を制御することで回避が可能です。
Cubism SDK for Unity では各コンポーネントの実行順をのCubismUpdateControllerで制御しているので、これを利用することもできます。
また、上記3種類の設定方法はそれぞれが同じ値を操作しているため、工夫無しで一つのモデルに共存させることは難しくなっております。
モーションによって値を操作
まばたき用のパラメータを設定したモデルを使用してCubismのAnimatorでモーションを作成する場合、まばたき用のカーブを設定することが可能です。
まばたき用のカーブが設定された.motion3.jsonをUnityプロジェクトにインポートした場合、AnimationClipにはCubismMouthController.MouthOpeningの値を対象としてそのカーブが生成されます。
そのため、そのAnimationClipをAnimatorコンポーネントなどで再生することでCubismMouthController.MouthOpeningの値が操作されます。
周期的に値を操作
周期的にリップシンク用の値を操作させるには、CubismAutoMouthInputを使用します。
CubismAutoMouthInputは、正弦波でリップシンクの値を算出して設定するコンポーネントです。
CubismAutoMouthInputを使用するには、CubismのPrefabのルートにアタッチします。
CubismAutoMouthInputには1つの設定項目があります。
- Timescale
正弦波の周期が変化します。
/// <summary> /// Timescale. /// </summary> [SerializeField] public float Timescale = 10f;
/// <summary> /// Called by Unity. Updates controller. /// </summary> /// <remarks> /// Make sure this method is called after any animations are evaluated. /// </remarks> private void LateUpdate() { // Fail silently. if (Controller == null) { return; } // Progress time. T += (Time.deltaTime * Timescale); // Evaluate. Controller.MouthOpening = Mathf.Abs(Mathf.Sin(T)); }
AudioClipからサンプリングして値を操作
Unity上で再生される音声からリップシンクの値を設定する場合はCubismAudioMouthInputを使用します。
CubismAudioMouthInputは、AudioSourceから取得した再生中の音声情報からサンプリングしてリアルタイムにリップシンクの値を生成、設定します。
CubismAudioMouthInputを使用するには、CubismのPrefabのルートにアタッチします。
/// <summary> /// Samples audio input and applies it to mouth controller. /// </summary> private void Update() { // 'Fail' silently. if (AudioInput == null) { return; } // Sample audio. var total = 0f; AudioInput.GetOutputData(Samples, 0); for (var i = 0; i < Samples.Length; ++i) { var sample = Samples[i]; total += (sample * sample); } // Compute root mean square over samples. var rms = Mathf.Sqrt(total / Samples.Length) * Gain; // Clamp root mean square. rms = Mathf.Clamp(rms, 0.0f, 1.0f); // Smooth rms. rms = Mathf.SmoothDamp(LastRms, rms, ref VelocityBuffer, Smoothing * 0.1f); // Set rms as mouth opening and store it for next evaluation. Target.MouthOpening = rms; LastRms = rms; }
CubismAudioMouthInputには4つの設定項目があります。
/// <summary> /// Audio source to sample. /// </summary> [SerializeField] public AudioSource AudioInput; /// <summary> /// Sampling quality. /// </summary> [SerializeField] public CubismAudioSamplingQuality SamplingQuality; /// <summary> /// Audio gain. /// </summary> [Range(1.0f, 10.0f)] public float Gain = 1.0f; /// <summary> /// Smoothing. /// </summary> [Range(0.0f, 1.0f)] public float Smoothing;
- AudioInput
サンプリングするAudioSourceの参照です。
- SamplingQuality
サンプリングする音声の精度です。
- Gain
サンプリングした値の倍率です。
1で等倍、値を大きくするほどリップシンクの値も大きくなります。
- Smoothing
サンプリングした値のスムージング量です。
値が大きいほどリップシンクの値が滑らかに変化します。