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:播放动画的优先级。将其插入当前播放的动画并播放时,将其设置为大于为该动画设置的优先级的值。
  • bool isLoop:是否循环播放动画,默认为循环播放。
  • float speed:动画播放速度,范围为0或更大,默认为1(正常播放速度)。

动画停止

使用CubismMotionController.StopAnimation(int animationIndex, int layerIndex = 0)停止指定索引的动画。

  • int animationIndex:要停止的动画的索引。
  • int layerIndex:要停止的动画的层索引。

使用CubismMotionController.StopAllAnimation()停止所有动画。

播放和停止动画时的回调

Cubism SDK for Unity允许您在播放和停止动画时使用回调获取Event。

播放动画时的回调

以下是播放动画时接收回调的范例代码。以该模型已提前载入为前提。

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时

请问这篇文章对您有帮助吗?
关于本报道,敬请提出您的意见及要求。