MotionFade
最終更新: 2019年3月28日
概述
使用MotionFade重现与Unity上的Viewer for OW相同的动态渐变和参数渐变。
单击此处了解有关Cubism动态渐变和参数渐变的更多信息。
在Viewer for OW中,当切换动态时,每个动态都会在缓动时淡入/淡出。
但是在Unity中,当动画切换时,只是一个没有缓动的直线渐变,而这个功能用来表达和Viewer for OW一样的渐变。
MotionFade执行以下处理:
- 创建[.fade.asset]
- 创建[.fadeMotionList]并追加[.fade.asset]
- 保存AnimationClip instanceID
- 创建播放动态列表
- 渐变计算与应用
创建[.fade.asset]
[.fade.asset]是一个ScriptableObject资产,其中包含一条从[motion3.json]转换并用于渐变的混合曲线。
载入[motion3.json]时会与AnimationClip一起生成[.fade.asset]。
如果变更[.fade.asset],则无法保证正常运行。
要将[exp.json]转换为[.fade.asset],请执行以下处理:
- 解析[motion3.json]
- 创建CubismFadeMotionData
- 创建[.fade.asset]
解析[motion3.json]
要[motion3.json]的解析,使用CubismMotion3Json.LoadFrom(string motion3Json)或CubismMotion3Json.LoadFrom(TextAsset motion3JsonAsset)。
- string motion3Json[motion3.json]的字符串。
- TextAsset motion3JsonAsset[motion3.json]文本文件资产。
创建CubismFadeMotionData
CubismFadeMotionData是一个记录渐变信息的类,保存以下信息:
场地 | 型 | 说明 |
MotionName | string | 动态名称。 |
FadeInTime | float | 直到动态淡入的时间。值的单位是秒。 |
FadeOutTime | float | 直到动态淡出的时间。值的单位是秒。 |
ParameterIds | string[] | 动态使用的参数ID。 |
ParameterCurves | AnimationCurve[] | 动态应用于参数的曲线。 |
ParameterFadeInTimes | float[] | 由于参数渐变,参数淡入所需的时间。值的单位是秒。如果设置了负值,将应用FadeInTime。 |
ParameterFadeOutTimes | float[] | 由于参数渐变,参数淡出所需的时间。值的单位是秒。如果设置了负值,将应用FadeOutTime。 |
MotionLength | float | 该动态的长度。值的单位是秒。 |
使用CreateInstance创建一个新的[.fade.asset]并通过覆盖保存它。
如果您传递已生成的CubismFadeMotionData副本作为第一参数,则该副本将被覆盖和处理。
CubismFadeMotionData.CreateInstance(CubismMotion3Json motion3Json, string motionName, float motionLength, bool shouldImportAsOriginalWorkflow = false, bool isCallFormModelJson = false); CubismFadeMotionData.CreateInstance(CubismFadeMotionData fadeMotion, CubismMotion3Json motion3Json, string motionName, float motionLength, bool shouldImportAsOriginalWorkflow = false, bool isCallFormModelJson = false);
参数 | 型 | 说明 |
fadeMotion | CubismFadeMotionData | 覆盖对象CubismFadeMotionData。 |
motion3Json | CubismMotion3Json | 解析为.motion3.json的数据。 |
motionName | string | 动态名称。 |
motionLength | float | 动态的长度。值的单位是秒。 |
shouldImportAsOriginalWorkflow | bool | 是否作为OriginalWorkflow载入。 |
isCallFormModelJson | bool | 是从model3.json的载入处理中调用的吗? |
创建[.fade.asset]
[.fade.asset]是使用AssetDatabase.CreateAsset()创建的。
// 创建时 fadeMotion = CubismFadeMotionData.CreateInstance( importer.Motion3Json, importer.AssetPath.Replace(directoryPath, ""), animationClip.length, CubismUnityEditorMenu.ShouldImportAsOriginalWorkflow, CubismUnityEditorMenu.ShouldClearAnimationCurves); AssetDatabase.CreateAsset(fadeMotion, importer.AssetPath.Replace(".motion3.json", ".fade.asset")); // 更新已创建的资产时 fadeMotion = CubismFadeMotionData.CreateInstance( oldFadeMotion, importer.Motion3Json, importer.AssetPath.Replace(directoryPath, ""), animationClip.length, CubismUnityEditorMenu.ShouldImportAsOriginalWorkflow, CubismUnityEditorMenu.ShouldClearAnimationCurves); EditorUtility.CopySerialized(fadeMotion, oldFadeMotion); // 更新Unity数据库 EditorUtility.SetDirty(fadeMotion);
该处理通过CubismFadeMotionImporter.OnFadeMotionImport()进行。
创建[.fadeMotionList]并追加[.fade.asset]
[.fadeMotionList.asset] 是一个资产,它包含一组与[.fade.asset]配对的AnimationClip副本ID。
[.fade.asset]列表的顺序是按照[motion3.json]的载入顺序追加的。
如果变更[.fadeMotionList.asset],则无法保证正常运行。
创建[.fadeMotionList]
在与模型预制相同的层次结构中创建[.fadeMotionList.asset]。
// 创建fadeMotionList fadeMotions = ScriptableObject.CreateInstance<CubismFadeMotionList>(); fadeMotions.MotionInstanceIds = new int[0]; fadeMotions.CubismFadeMotionObjects = new CubismFadeMotionData[0]; AssetDatabase.CreateAsset(fadeMotions, fadeMotionListPath);
该处理通过CubismFadeMotionImporter.OnFadeMotionImport()进行。
追加[.fade.asset]
要将[.fade.asset]追加到[.fadeMotionList.asset],进行以下操作:
// 更新现有数据时 fadeMotions.CubismFadeMotionObjects[motionIndex] = fadeMotion; // 追加新数据时 motionIndex = fadeMotions.MotionInstanceIds.Length; Array.Resize(ref fadeMotions.MotionInstanceIds, motionIndex+1); fadeMotions.MotionInstanceIds[motionIndex] = instanceId; Array.Resize(ref fadeMotions.CubismFadeMotionObjects, motionIndex+1); fadeMotions.CubismFadeMotionObjects[motionIndex] = fadeMotion; // 更新Unity数据库 EditorUtility.SetDirty(fadeMotions);
该处理通过CubismFadeMotionImporter.OnFadeMotionImport()进行。
保存AnimationClip instanceID
AnimationClip的副本ID在该AnimationClip中保存为AnimationEvent。
* 由于AnimationClip.GetInstanceID()获得的副本ID可能因执行环境不同而在Unity和运行时间不同,因此可能无法确定AnimationClip。
// 获取保存副本ID的Event var sourceAnimEvents = AnimationUtility.GetAnimationEvents(animationClip); AnimationEvent instanceIdEvent= null; for(var i = 0; i < sourceAnimEvents.Length; ++i) { if(sourceAnimEvents[i].functionName != "InstanceId") { continue; } instanceIdEvent= sourceAnimEvents[i]; break; } // 如果没有保存副本ID的Event,则追加Event if(instanceIdEvent== null) { instanceIdEvent= new AnimationEvent(); Array.Resize(ref sourceAnimEvents, sourceAnimEvents.Length + 1); sourceAnimEvents[sourceAnimEvents.Length - 1] = instanceIdEvent; } // 设置副本ID instanceIdEvent.time = 0; instanceIdEvent.functionName = "InstanceId"; instanceIdEvent.intParameter = instanceId; instanceIdEvent.messageOptions = SendMessageOptions.DontRequireReceiver; // 在AnimationClip中设置Event AnimationUtility.SetAnimationEvents(animationClip, sourceAnimEvents);
该处理通过CubismFadeMotionImporter.OnFadeMotionImport()进行。
创建播放动态列表
播放动态列表是计算渐变时参考的列表,它还保存有关使用CubismFadePlayingMotion播放的动态信息。
关于CubismFadePlayingMotion
CubismFadePlayingMotion是一个具有以下动态播放信息和渐变信息的类。
- StartTime:动态播放开始时间。值的单位是秒。
- EndTime:动态的退出时间。值的单位是秒。
- FadeInStartTime:动态淡入开始时间。值的单位是秒。
- Speed:动态播放速度。速度范围为0或更大。1与Cubism Editor中设置的速度相同。
- Motion:包含动态渐变信息的CubismFadeMotionData。
关于ICubismFadeState
ICubismFadeState是一个用于获取渐变计算所需信息的接口。
ICubismFadeState的API:
- List
GetPlayingMotions() - 获取播放动态列表。
- bool IsDefaultState()
- 是否为默认状态。
- float GetLayerWeight()
- 获取层的权重。
- bool GetStateTransitionFinished()
- 过渡是否退出。
- void SetStateTransitionFinished(bool isFinished)
- 设置过渡的退出。
- void StopAnimation(int index)
- 停止播放由索引指定的动画。
关于CubismFadeStateObserver
CubismFadeStateObserver是一个继承ICubismFadeState,监控Animator的状态,创建播放动态列表的类。
播放动态列表使用在播放动画时调用的OnStateEnter()进行创建。
// 获取播放的AnimationClips var animatorClipInfo = controller.GetNextAnimatorClipInfo(layerIndex); // 设置正在播放的动画的退出时间 for (var i = 0; i < _playingMotions.Count; ++i) { var motion = _playingMotions[i]; if (motion.Motion == null) { continue; } var newEndTime = Time.time + motion.Motion.FadeOutTime; if (motion.EndTime < 0.0f || newEndTime < motion.EndTime) { motion.EndTime = newEndTime; } } // 创建和追加播放动画 for (var i = 0; i < animatorClipInfo.Length; ++i) { CubismFadePlayingMotion playingMotion; /*省略*/ playingMotion.Motion = (motionIndex == -1) ? null : _cubismFadeMotionList.CubismFadeMotionObjects[motionIndex]; playingMotion.Speed = 1.0f; playingMotion.StartTime = Time.time; playingMotion.FadeInStartTime = Time.time; playingMotion.EndTime = (playingMotion.Motion.MotionLength <= 0) ? -1 : playingMotion.StartTime + playingMotion.Motion.MotionLength + playingMotion.Motion.FadeOutTime; _playingMotions.Add(playingMotion); }
该处理通过CubismFadeMotionImporter.OnFadeMotionImport()进行。
渐变计算与应用
渐变的计算和应用使用CubismFadeController.UpdateFade()进行。
MotionFade必须在动画处理之后应用。