Motion

最終更新: 2024年11月28日

概要

Motionを使用することで、UnityのMecanimでステートマシンを組まずにスクリプトからアニメーションを再生することができます。

Motionを使用するにはCubismFadeControllerコンポーネントとUnityのAnimatorが必要です。
AnimatorコンポーネントにAnimatorControllerを設定した場合、Motionは再生されずにAnimatorControllerのアニメーションが再生されます。

該当のチュートリアル記事は スクリプトからモーションを再生させる をご覧ください。

Motionは以下の処理を行っています。

  1. PlayableGraphを作成
  2. CubismMotionLayerを作成
  3. アニメーション再生
  4. アニメーション停止

PlayableGraphを作成

PlayableGraphはアニメーションなどを出力するためのものです。
こちらの詳細は、Unity公式のドキュメントをご覧ください。

// Animator側のPlayableGraphを無効
var graph = animator.playableGraph;
if(graph.IsValid())
{
    graph.GetOutput(0).SetWeight(0);
}

// PlayableGraphを作成
_playableGraph = PlayableGraph.Create("Playable Graph : " + this.FindCubismModel().name);
_playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);

// 結果出力用のPlayable作成
_playableOutput = AnimationPlayableOutput.Create(_playableGraph, "Animation", animator);
_playableOutput.SetWeight(1);

// レイヤーを合成するPlayable作成
_layerMixer = AnimationLayerMixerPlayable.Create(_playableGraph, LayerCount);

// デフォルト出力先を設定
_playableOutput.SetSourcePlayable(_layerMixer);

この処理はCubismMotionController.OnEnable()で行っています。

CubismMotionLayerを作成

CubismMotionLayerを利用すると、複数のモーションを並列して再生させることができます。

// Create cubism motion layers.
_motionLayers = new CubismMotionLayer[LayerCount];
for(var i = 0; i < LayerCount; ++i)
{
    _motionLayers[i] = CubismMotionLayer.CreateCubismMotionLayer(_playableGrap, _cubismFadeMotionList);
    _motionLayers[i].AnimationEndHandler += OnAnimationEnd;
    _layerMixer.ConnectInput(i, _motionLayers[i].PlayableOutput, 0);
    _layerMixer.SetInputWeight(i, 1.0f);
}

この処理はCubismMotionController.OnEnable()で行っています。

複数のレイヤーでモーションを同時に再生させたときに、それらが同一のCubismParameter.Valueを操作すると、後に設定される値で上書きされます。
上書きするウェイトは、CubismMotionLayer.SetLayerWeight(float weight)で設定することができます。
CubismMotionLayerにウェイトを設定した場合、AnimationLayerMixerPlayableにも同時にウェイトを設定する必要があります。

AnimationLayerMixerPlayableの詳細は、Unity公式のドキュメントをご覧ください。

_motionLayers[layerIndex].SetLayerWeight(weight);
_layerMixer.SetInputWeight(layerIndex, weight);

アニメーション再生

CubismMotionController.PlayAnimation(AnimationClip clip, int layerIndex = 0, int priority = CubismMotionPriority.PriorityNormal, bool isLoop = true, float speed = 1.0f) を使うことで、アニメーションの再生ができます。

  • AnimationClip clip:再生するアニメーションクリップ。
  • int layerIndex:アニメーション再生レイヤーのインデックス。
  • int priority:再生するアニメーションの優先度。現在再生されているアニメーションに差し込んで再生させる場合、そのアニメーションに設定されたpriorityよりも大きな値にする。
  • bool isLoop:アニメーションはループ再生かどうか、デフォルトはループ再生。
  • float speed:アニメーションの再生速度、範囲は0以上、デフォルトは1(通常の再生速度)。

アニメーション停止

指定インデックスのアニメーションを停止する場合は CubismMotionController.StopAnimation(int animationIndex, int layerIndex = 0) を使います。

  • int animationIndex:停止するアニメーションのインデックス。
  • int layerIndex:停止するアニメーションのレイヤーインデックス。

すべてのアニメーションを停止する場合は CubismMotionController.StopAllAnimation() を使います。

アニメーション再生時と停止時のコールバック

Cubism SDK for Unity ではアニメーション再生時とアニメーション停止時にコールバックによるイベント取得を行えます。

アニメーション再生時のコールバック

アニメーション再生時にコールバックを受け取るサンプルコードは下記です。モデルが事前にインポートされていることを前提としています。

private CubismMotionController _motionController;
private CubismFadeMotionList _cubismFadeMotionList;

// Start is called before the first frame update
private void Start()
{
    _motionController = GetComponent<CubismMotionController>();

    _cubismFadeMotionList = GetComponent<CubismFadeController>().CubismFadeMotionList;
    _motionController.AnimationBeginHandler += OnAnimationBegin;
}

private void OnAnimationBegin(int instanceId)
{
    if (!_cubismFadeMotionList)
    {
        return;
    }

    for (int i = 0; i < _cubismFadeMotionList.MotionInstanceIds.Length; i++)
    {
        if (_cubismFadeMotionList.MotionInstanceIds[i] != instanceId)
        {
            continue;
        }

        Debug.Log("StartedMotion: " + _cubismFadeMotionList.CubismFadeMotionObjects[i].MotionName);
        break;
    }
}

このコードでは CubismMotionController.AnimationBeginHandler に自身で作成した OnAnimationBegin() 関数を登録します。

Tips

以下の状態では再生時のコールバックは動作しません。

  • コールバックにnullが登録されているとき

アニメーション終了時のコールバック

アニメーション再生時にコールバックを受け取るサンプルコードは下記です。

private CubismMotionController _motionController;
private CubismFadeMotionList _cubismFadeMotionList;

// Start is called before the first frame update
void Start()
{
    _motionController = GetComponent<CubismMotionController>();

    _cubismFadeMotionList = GetComponent<CubismFadeController>().CubismFadeMotionList;
    _motionController.AnimationEndHandler += OnAnimationEnd;
}

void OnAnimationEnd(int instanceId)
{
    if (!_cubismFadeMotionList)
    {
        return;
    }

    for (int i = 0; i < _cubismFadeMotionList.MotionInstanceIds.Length; i++)
    {
        if (_cubismFadeMotionList.MotionInstanceIds[i] != instanceId)
        {
            continue;
        }

        Debug.Log("EndedMotion: " + _cubismFadeMotionList.CubismFadeMotionObjects[i].MotionName);
        break;
    }
}

このコードでは CubismMotionController.AnimationEndHandler に自身で作成した OnAnimationEnd() 関数を登録します。
アニメーションの再生終了時あるいは停止時にこのコールバックは呼び出されます。

Tips

以下の状態では終了時のコールバックが呼び出せないのでご注意ください

  • 再生中のモーションが「ループ」として設定されているとき
  • コールバックにnullが登録されているとき

この記事はお役に立ちましたか?
はいいいえ
この記事に関するご意見・
ご要望をお聞かせください。