【Unity-Timeline】学习笔记
Timeline:强大的可视化流程控制工具
官方文档:https://docs.unity3d.com/Packages/com.unity.timeline@1.8/manual/index.html
前言
Timeline
是Unity中的一个强大的可视化工具,用于创建、编辑和控制复杂的时间线动画和剧情序列,可以轻松实现剪辑、动画、特效和音频的精确时间控制和协调
而从笔者目前的了解来说,Timeline
可以做的远不止“做剧情过程”这么简单,其本质上是一个强大的可视化时间轴控制器,我们可以通过其实现一定程度的流程控制,即从某一时刻开始以既定序列执行一系列事件,而得益于其提供了可供自定义的接口,这个“事件”的定义可以非常广泛,如可以用其实现:在玩家按下开火键后立刻触发一个粒子特效,3帧后,生成子弹预制体,1秒后播放玩家动画
之类的效果
如果只从这个角度来说,Animation
组件也可以实现这一效果,但其只能承载一些比较简单的流程控制,并且可视化编辑体验并不算好;而Timeline
相比来说更加强大,可供拓展的范围更广,并且可以实现一定程度的节点复用,在可视化编辑体验上来说也更加现代;同时,Timeline
也可以很好地和原先的Animation
系统交互
之前在Unity中,若要在不借助第三方插件的前提下进行较为精确的时间轴控制,往往使用协程或难用的Animation
,而Timeline
可以说补足了Unity功能的一大空缺,可以说非常强大了
Timeline概念概述
运作方式:Timeline与Animation
在整体的运作方式上,Timeline
与Animation
非常相像;在使用Animation
时,我们需要创建Animation Clip
资源文件,并在对应物体上挂载Animation
/Animator
组件,通过组件驱动Animation Clip
进行播放;而Timeline
与其几乎一样,我们需要创建Timeline
资源文件,并在物体上挂载Playable Director
组件,通过其来驱动Timeline
进行播放
而二者不同的地方在于,Animation
在设计上是与挂载了Animation
/Animator
组件物体高度相关的,即动画应该是属于某一物体的,一段主角身上的动画应该是属于主角的,其应该只影响主角,我们当然也可以通过一些手段让其控制其他物体,但总的来说很不方便也很不优雅;而在Timeline
中,Playable Director
正如其名只是一个“导演”,其只承担Timeline
的驱动和管理,而可以不与Timeline
所影响的物体相关,即导演在大部分情况下不会参演其导演的作品,这赋予了Timeline
无比的自由度,你可以在其中控制场景中的一切
构成方式:Track - Clip
了解了Timeline
的大体运作方式后,我们该认识一个Timeline
的构成了;实际上,如果你了解或使用过任何视频剪辑软件,如:PR、达芬奇,你便会对Timeline
的结构一目了然,Timeline
的构成方式与视频剪辑软件非常相似
Track:
- 一个
Timeline
由0~N个Track
构成,Track
是一个无限长的时间轴,一个Timeline
中的所有Track
共用一个时间轴 Track
的存在允许我们方便地管理多个物体的行为,如我们希望A物体在1.0s出现、3.0s小时,B物体在2.0s出现、4.0s消失,我们便可以使用两个Track
来实现这点Track
有不同的类型,其描述了Track
的基本功能,Unity已经为我们提供了一些预制好的Track
,如最基本的Activation Track
便是控制一个物体的Active
状态的
Clip:
一个
Track
由0~N个Clip
构成,Clip
是一个有开始时间和结束时间的区块,其存在于Track
之上,当时间运行到对应Clip
时,其便会执行对应行为Clip
允许我们对物体的状态在时间轴上进行精确的并行的控制,其与Track
的结合可以很好地帮助我们实现想要的效果
需要注意的是,Track和Clip本身实际上都不具有具体的功能,它们都是回调的触发者,真正的逻辑位于Behavior之上,这点在后续的自定义Track部分会详细说明
各默认Track介绍
Activation Track
Activation Track
用于在特定时间启用或禁用游戏对象
Track上可以绑定一个GameObject
对象(这一对象最好不是Director,禁用Director将会终止Timeline的播放),一个Activation Track
只能控制一个对象;Clip则决定了对象显隐的具体时间
需要注意的是,Clip在设计上是从属于Track的,从抽象层来说不应该访问Track上的数据(被控制对象的引用是绑定在Track上的),此处实际上使用了Track Mixer
进行实现,在后续的自定义Track部分会详细说明
Animation Track
Animation Track
用于播放Animator控制器上的动画片段(Animation Clip
)
Track上可以绑定一个Animator
对象,Clip则由对象的动画片段构成;同时,Track上实现了Track Mixer
,我们可以将两个的Clip进行重叠,实现动画的平滑过渡,并且自由地编辑过渡曲线
Audio Track
Audio Track
用于控制音频的播放
Track上可以绑定一个Audio Source
对象,该对象用于播放音频;而Clip则是具体需要播放的音频片段(Audio Clip
);同时,其也实现了Track Mixer
,我们可以将两个的Clip进行重叠,实现音频的平滑过渡,并且自由地编辑过渡曲线
Control Track
Control Track
允许你控制其他Player Director
的播放,可以用来触发其他Timeline
其Track上没有数据,Clip则由其他Player Director
构成
Playable Track
Playable Track
较为特殊,其本身没有实际的逻辑,但其可以驱动自定义Clip
当我们想进行一定程度的自定义,但不需要用到Track时,我们便可以只自定义Clip,并在Playable Track
对其进行应用
Signal Track
Signal
是Timeline中内置的“事件系统”,其基于观察者模式进行搭建,如果你有使用过事件中心,那么你便能很快上手这个概念
在使用它时,我们需要先右击创建后缀为.signal
的资产文件,这相当于事件系统中的“事件”,需要注意的时,其本身不具有逻辑,其只是一个“概念”,一个逻辑的容器
之后我们需要在事件作用的对象身上创建Signal Receiver
组件,在其之上,我们便可以在Inspector
中对需要触发的事件进行绑定,如下图所示
这一组件是时间的“订阅者”,需要注意的是,Signal
在这一过程中是可以被复用的,一个Signal
可以被绑定给多个Reveiver
之后,我们便可以右击Track,选择Add Signal Emitter
,当Track运行到该节点时,对应Signal
便会被触发
事实上,我们可以在任何Track上添加Signal Emitter
,而独立出来的Signal Track
或许是希望让Signal
的触发更加容易管理
Signal系统由于基于Timeline而生,在某些情况下并不那么好用,因其只支持在Inspector中进行事件的绑定,有时然而会让事情变得复杂,难以管理,或许我们可以在之后使用自定义Track功能创建自己的事件系统
Cinemachine Track
这并不是Timeline中自带的功能,其由Cinemachine
插件提供
其可以非常方便地通过Timeline控制Cinemachine
中的虚拟相机,是个非常强大便捷的功能
Cinemachine
不是本文的主角,故此处对其用法不过多赘述
自定义Track
概述
接下来终于来到了个人认为Timeline中最激动人心的部分:强大的自定义功能
Unity为我们提供了TrackAsset
、PlayableAsset
与PlayableBehaviour
三个类与一些接口,通过继承它们,我们便可以实现对于Track的完全自定义
上面介绍过的Timeline提供的默认Track也都是通过这些类实现的,其没有被写在Unity内核中,这也意味着我们可以在项目中直接找到实现它们的C#代码,这相当于官方范例,我想这可以给我们的自定义带来很大的帮助
上图展示了一个完整Track的基本构成方式(括号中是它们背后的类)
PlayerBehaviour
是承载具体逻辑的基类,其具有多个回调,如OnBehaviourPlay
(开始调用时)、ProcessFrame
(每个逻辑帧)等;其既可以绑定在Clip上也可以由Track创建PlayableAsset
是Clip的基类,实现其CreatePlayable
函数即可将一个PlayerBehaviour
与其绑定,从而触发PlayerBehaviour
中的回调函数TrackAsset
是Track的基类,其定义了一个Track的方方面面,包括Track上绑定的物体的类型、Track上Clip的类型、Track的颜色等;而实现CreateTrackMixer
可以将一个PlayerBehaviour
与其绑定,我们通常称其为Mixer,其可以访问整个Track上的绑定对象与其中的Clip的数据;尽管绑定在Clip上的PlayerBehaviour
实际上也可以获取到Track上的绑定对象,但从面向对象的角度出发,和Track绑定对象相关的逻辑应该写在Mixer中,同时Mixer也负责处理Clip之间的融合逻辑,例如默认Track中的Animation Track
与Audio Track
便实现了对应功能
具体实现
Track类
1 | namespace Timeline |
Clip类
1 | namespace Timeline |
Behavior类
1 | namespace Timeline |
Mixer类
1 | namespace Timeline |