Motion
最終更新: 2024年11月28日
概述
通过使用Motion,您可以从脚本播放动画,而无需使用Unity的Mecanim构建状态机。
要使用Motion,您需要CubismFadeController组件和Unity的Animator。
如果在Animator组件中设置AnimatorController,则不会播放Motion,而是播放AnimatorController的动画。
有关相应的教程文章,请参考通过脚本播放动态。
Motion执行以下处理。
- 创建PlayableGraph
- 创建CubismMotionLayer
- 动画播放
- 动画停止
创建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时