实现效果

核心功能

  1. 支持选定模型(带Animator)在非运行模式下,播放/暂停/停止动作。
  2. 支持动作单帧前进,单帧回退(帧时间默认0.05f,可以代码设置)。
  3. 支持滚动条拖拽,将动作调整到指定时间。
  4. 支持调整播放速度。

其他功能

  1. 支持循环播放。
  2. 支持选中Animator下的任一动作。
  3. 编辑器关闭时,会删除中间产生的临时GameObject
  4. 选中Project中的Prefab,如果符合条件,将会自己创建一份Clone到Hierarchy中。

效果图

实现原理

整体思路

  1. 获取指定GameObject上的Animator,并记录其所有的AniamtionClip。
  2. 模拟播放时间,通过AnimationMode.SampleAnimationClip方法设置播放位置。
  3. 添加进度条,单帧执行等方式修改播放时间。

注意细节

  1. 如果模型勾选了OptimizeGameObject选项,优化骨骼,那么动作可能会因为找不到骨骼而无法播放。需要使用AnimatorUtility.DeoptimizeTransformHierarchy方法,暂时屏蔽骨骼优化。
  2. 在使用AnimationMode.SampleAnimationClip方法时,参数的GameObject应该设置为Animator所对应的GameObject而不是根节点。
  3. 因为不是运行状态,所以Update需要由EditorApplication.update提供。(工具关闭时,需要反注册)
  4. OnGUI方法不是每帧都执行,当使用滚动条( Slider )和进度条(ProgressBar)时,显示不会及时更新,所以当数据更新时,需要调用Repaint方法,强制刷新UI。
  5. EditorWindow下,OnSelectionChange方法可以用来监听选择变化。但是在这个方法内部,修改当前选中的对象(Selection的属性)无效。
  6. 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, "");
}

存在疑问

  1. AnimationMode文档中说在使用 SampleAnimationClip时需要 StartAnimationMode,但没有调用,也是可以正常运行。BeginSampling,EndSampling作用什么?不加也可以正常运行。
  2. 在使用AnimatorUtility.OptimizeTransformHierarchy去还原模型时,需要知道exposedTransforms即需要保留的骨骼。但是没有找到获取exposedTransforms的方法,所以GameObject在被DeoptimizeTransformHierarchy之后无法还原。一种的思路是在调用DeoptimizeTransformHierarchy之前记录子Transform,并且去掉包含SkinnedMeshRender的Transform,使用这些Transform来当做exposedTransforms。但是这种方式不精确,对模型有限制。

ToDo

  1. 倒播。修改时间变化方式,添加符号判断。
  2. ParticleSystem.Simulate可以在非运行模式下制定特效播放到制定时间,可以用这个方法实现一套特效的播放回退机制。(特效比较复杂可能包含多个ParticleSystem,也可能包含动画)
  3. 结合动作和特效,实现特效与模型动作的匹配,指定特效延时时间,并且可以同时处理多个特效。(类似技能编辑器的表现)

源码下载

转载请注明出处:http://www.cnblogs.com/chiguozi/p/6862571.html

Unity非运行模式下实现动画播放/回退工具的更多相关文章

  1. 非GUI模式下运行JMeter和远程启动JMeter

    JMeter是一款非常不错的免费开源压力测试工具,越来越多的公司在使用.不过,在使用过程中可能会存在一些问题,比如:GUI模式非常消耗资源,单个客户端测试无法达到目标压力.而使用非 GUI 模式,即命 ...

  2. 测试Oracle 11gr2 RAC 非归档模式下,offline drop数据文件后的数据库的停止与启动测试全过程

    测试Oracle 11gr2 RAC 非归档模式下,offline drop数据文件后的数据库的停止与启动测试全过程 最近系统出现问题,由于数据库产生的日志量太大无法开启归档模式,导致offline的 ...

  3. 非归档模式下使用Rman进行备份和恢复

    实验环境: 一.首先进行全库数据备份: 在非归档模式下,rman备份需要在mount模式下进行 SQL> select status from v$instance; STATUS ------ ...

  4. socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto

    socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...

  5. Oracle非归档模式下脱机数据文件

    正常情况下,要想对数据文件脱机,必须在归档模式下,这是ORACLE自动保护的一种措施,防止在非归档模式下对数据文件脱机,造成数据丢失.如果想在非归档模式下执行数据文件脱机操作,则需要加上“for dr ...

  6. 非IMU模式下DML语句产生的REDO日志内容格式解读

    实验内容:非IMU模式下DML语句产生的REDO日志内容格式解读 最详细的解读是UPDATE的. 实验环境准备 11G中默认是开启IMU特性的,做此实验需要关闭此特性. alter system se ...

  7. 使用alter database datafile 'XXX' offline drop 是否能够恢复(非归档模式下)

    今天在群里面听到一位网友在说使用了alter database datafile 'XXX' offline drop命令是否能够恢复数据,在非归档模式下,下面是用一个实验来验证一下 ######## ...

  8. oracle非归档模式下的冷备份和恢复

    查看归档的相关信息 SQL> archive log list数据库日志模式             非存档模式自动存档             禁用存档终点            USE_DB ...

  9. IE兼容模式与非兼容模式下jq的写法

    1.  $("#LabelRepeatType").removeAttr("disabled");                $("#LabelF ...

随机推荐

  1. oracle删除字段中的空格、回车及指定字符

    create or replace procedure PROC_test is --Description:删除字段中的指定字符(回车chr(13).换行chr(10)) --By LiChao - ...

  2. PRINCE2重要性--光环国际培训

    项目的重要性 答:对于当今的组织来说,一个关键的挑战,就是能够成功地平衡以下两个并存的.互相竞争的方面:保持现有的商业运营--盈利能力.服务质量.客户关系.品牌忠实度.生产效率.市场信心等,这些被称为 ...

  3. 原创SQlServer数据库生成简单的说明文档小工具(附源码)

    这是一款简单的数据库文档生成工具,主要实现了SQlServer生成说明文档的小工具,目前不够完善,主要可以把数据库的表以及表的详细字段信息,导出到 Word中,可以方便开发人员了解数据库的信息或写技术 ...

  4. 性能调优之MYSQL高并发优化

    性能调优之MYSQL高并发优化   一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之 ...

  5. C语言常见错误笔记

    1. 职业化的程序员起码要具备两点: 1)基本的软件技能 2)不犯低级的错误 2. 修改函数的形参是没用的,函数本身占用的存储单元在堆栈中分配,入口参数的值会在函数入口处拷贝到堆栈中,一旦函数返回,其 ...

  6. RabbitMQ-从基础到实战(6)— 与Spring集成

    0.目录 RabbitMQ-从基础到实战(1)- Hello RabbitMQ RabbitMQ-从基础到实战(2)- 防止消息丢失 RabbitMQ-从基础到实战(3)- 消息的交换(上) Rabb ...

  7. 跟着刚哥梳理java知识点——多线程(十六)

    创建多线程第一种方式:① 继承:继承Thread.② 重写:重写Thread类的run()方法③ 创建:创建一个子类的对象④ 调用:调用线程的start()方法,启动此线程,调用run()方法 cla ...

  8. 自动获取代理IP信息的例子,含代码,分享哦,

    /// <summary> /// 读取URL数据内容 /// </summary> /// <param name="url">网址</ ...

  9. Android性能优化——之防止内存泄露

    又是好久没有写博客了,一直都比较忙,最近终于有时间沉淀和整理一下最近学到和解决的一些问题. 最近进行技术支持的时候,遇到了几个崩溃的问题,都是OOM异常,一般OOM异常给人的感觉应该是加载大图片造成的 ...

  10. dotnetcore中的IOptionsSnapshot<>的自动更新原理

    1.首先讲讲ChangeToken.OnChange方法: 原理是给一个CancellationToken注册一个消费者委托,调用CancellationToken的Cancel的时候会调用这个Can ...