本人才疏学浅,如有错误还忘指正。
开发目的
本来是想用unityEditor从零写一个,后来发现unityTimeLine提供了这个功能,就使用TimeLine制作了。
通常动作游戏中的动作常伴随着复杂的随着时间变化的事件,所以开发动作游戏需要对动画逐帧去控制(如音效,特效,检测Box,按键检测,屏幕特效,相机动画),由于unity的Animator缺乏逐帧编辑的功能,而unity的TimeLine提供可自定义的Playable,可以很方便的扩展出自己的一套Playable(下图每一层的内容)。
具体思路:
将每个PlayableAsset制作成一个单独的动画和事件的集合体(上图便是一个Idle的PlayableAsset),通过PlayableDirector 控制它的播放模式(循环/只播放一次...),时间更新模式(不受时间影响/受游戏时间影响.....这里有个坑,设置UnScaledGameTime在编辑器修改不会起作用,只有在脚本中修改才会起作用),切换动画,暂停动画,停止动画。
我测试了一下,PlayableDirector 切换动画时如果动画是循环的,播放停止的事件不会执行,开始播放的动画会在每次循环开始的时候执行,在Hold模式下会正常执行。所以播放循环动画时需要将播放模式修改为循环模式,同理,切换单次播放的动画需要将模式修改为单次播放。
playableDirector.Stop(); playableDirector.extrapolationMode = DirectorWrapMode.Hold; playableDirector.Play(value);
播放完成判断需要自己用时间检测,stoped 的事件只有退出这个动画他才会执行。
if (playableDirector.time>=playableDirector.playableAsset.duration) { SwitchPlableAsset("Idle"); }
PlayableAsset示例:
上图第一层便是添加一个Animation Track,再右侧时间轴上选择添加一个AnimationClip.
第二层Colider 是伤害检测盒子(也可以是其它的物体,为了分层清晰就这样了)的激活失活控制
第三层控制AudioScore播放音频。
第四层五层是自己定义的Playable,可以在Clip所在帧内执行对应的事件。
第六层是控制时间缩放。
(上图仅供参考)可以在下面继续添加自己所需要的事件处理层。这只是简单示例,更复杂的需要自己去定义自己的Playable。
Playable 介绍
由于unity这块参考资料很少,我也了解不多 。更多关于Playable看这篇文章 https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247493316&idx=1&sn=7e4fef834a8066faca3d2f1f1a090bb4&chksm=fe1dd26fc96a5b79856840f556cf65026facb83520ac1891605e42d5e777d30a0d5219060e21&mpshare=1&scene=1&srcid=0606YJLYnfprk9UjpPQCnre1#rd
写法可参考 https://assetstore.unity.com/packages/essentials/default-playables-95266
PlayableBehaviour 提供执行PlayableClip所需要的数据。
重载方法里,OnBehaviourPlay()是时间轴到达Clip执行,OnBehaviourPause()是时间轴离开Clip执行,ProcessFrame()每帧都在执行。
在Clip范围内判断可以看下一篇文章 https://www.cnblogs.com/DazeJiang/p/14313198.html 。
playerData 是外部绑定的数据
通过属性绑定。
PlayableDirector也可以查看或添加绑定。拿到绑定的对象就可以在ProcessFrame()中控制其行为。
遇到的问题:
1.动画与动画之间的混合。目前设置Clip的混合时间他只会和上次播放的动画混合,混合后的姿势很奇怪没办法用。
解决思路:
在播放下一个动画时,将其于原动画混合,混合时间可以自己控制。正在解决中,尝试了下,PlayableDirector 无法对其playablegraph里的AnimationMixer动态添加AnimationClip,并进行混合,有点难搞。
上面试了试,还是用TimeLine编辑数据,解析TimeLineAsset 好更灵活。