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时