您的位置:首页 > 移动开发 > Unity3D

Unity非运行模式下实现动画播放/回退工具

2017-05-16 17:41 459 查看

实现效果

核心功能

支持选定模型(带Animator)在非运行模式下,播放/暂停/停止动作。

支持动作单帧前进,单帧回退(帧时间默认0.05f,可以代码设置)。

支持滚动条拖拽,将动作调整到指定时间。

支持调整播放速度。

其他功能

支持循环播放。

支持选中Animator下的任一动作。

编辑器关闭时,会删除中间产生的临时GameObject

选中Project中的Prefab,如果符合条件,将会自己创建一份Clone到Hierarchy中。

效果图



实现原理

整体思路

获取指定GameObject上的Animator,并记录其所有的AniamtionClip。

模拟播放时间,通过AnimationMode.SampleAnimationClip方法设置播放位置。

添加进度条,单帧执行等方式修改播放时间。

注意细节

如果模型勾选了OptimizeGameObject选项,优化骨骼,那么动作可能会因为找不到骨骼而无法播放。需要使用AnimatorUtility.DeoptimizeTransformHierarchy方法,暂时屏蔽骨骼优化。

在使用AnimationMode.SampleAnimationClip方法时,参数的GameObject应该设置为Animator所对应的GameObject而不是根节点。

因为不是运行状态,所以Update需要由EditorApplication.update提供。(工具关闭时,需要反注册)

OnGUI方法不是每帧都执行,当使用滚动条( Slider )和进度条(ProgressBar)时,显示不会及时更新,所以当数据更新时,需要调用Repaint方法,强制刷新UI。

EditorWindow下,OnSelectionChange方法可以用来监听选择变化。但是在这个方法内部,修改当前选中的对象(Selection的属性)无效。

ProgressBar不能使用Layout,需要自己设置Position。在Layout中获取上一个Rect的位置,然后计算ProcessBar的位置,实现方式:

if(Event.current.type == EventType.Repaint)
{
var lastRect = GUILayoutUtility.GetLastRect();
EditorGUI.ProgressBar(new Rect(lastRect.x, lastRect.y + lastRect.height, lastRect.width, 20), animationCtrl.escapeTime / animationCtrl.length, "");
}


存在疑问

AnimationMode文档中说在使用 SampleAnimationClip时需要 StartAnimationMode,但没有调用,也是可以正常运行。BeginSampling,EndSampling作用什么?不加也可以正常运行。

在使用AnimatorUtility.OptimizeTransformHierarchy去还原模型时,需要知道exposedTransforms即需要保留的骨骼。但是没有找到获取exposedTransforms的方法,所以GameObject在被DeoptimizeTransformHierarchy之后无法还原。一种的思路是在调用DeoptimizeTransformHierarchy之前记录子Transform,并且去掉包含SkinnedMeshRender的Transform,使用这些Transform来当做exposedTransforms。但是这种方式不精确,对模型有限制。

ToDo

倒播。修改时间变化方式,添加符号判断。

ParticleSystem.Simulate可以在非运行模式下制定特效播放到制定时间,可以用这个方法实现一套特效的播放回退机制。(特效比较复杂可能包含多个ParticleSystem,也可能包含动画)

结合动作和特效,实现特效与模型动作的匹配,指定特效延时时间,并且可以同时处理多个特效。(类似技能编辑器的表现)

源码下载

转载请注明出处:http://www.cnblogs.com/chiguozi/p/6862571.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐