Timeline给不同类型的对象建立不同的轨道,在每个轨道的时间线上我们可以组织动画播放、音频播放,游戏对象的显隐等操作,也可以自定义轨道完成一些个性化操作
使用Timeline需要Playable Director组件,它控制Timeline的播放,暂停,循环等功能,Timeline可以看作是剧本,Playable Director就是导演
名称 | 描述 |
---|---|
Playable | 引用Timeline资源 |
Update Method | 控制时间增加的方式 |
DSP,基于DSP(数字声音处理)时钟。对于需要与音频同步的图形,使用此选项 | |
GameTime,基于Time.time更新,默认选项 | |
UnscaledGameTime,基于Time.unscaledTime更新,即使游戏暂停,也需要对图形进行更新 | |
Manual,手动更新,使用PlayableGraph.Evaluate接口更新 | |
Play On Awake | 组件唤醒时是否自动播放 |
Wrap Mode | Hold,播放完停在最后一帧,Loop,循环播放,None,播放完回到第一帧 |
Initial Time | 从片段的第几秒开始播放 |
Bindings | 轨道上绑定的资源 |
在场景中选中某个游戏对象,Window -> Sequencing -> Timeline 打开Timeline窗口
点击Create创建Timeline Asset,它存储轨道及片段相关信息
也可以右键 -> Create -> Timeline,创建Timeline Asset,它以playable结尾
Timeline上可以创建多种类型的轨道,上方显示时间(秒或者帧),通过右上角齿轮切换,Frames是帧,Seconds和Timecode是秒,只是格式不一样
滚动鼠标中键调整时间显示范围,按住Ctrl,滚动鼠标中键,调整轨道宽度
Track Group
Track Group类似一个文件夹,把一些轨道放在一起形成一个Group,可以折叠起来,方便管理
Activation Track
这个轨道控制游戏对象是否激活,一个轨道只能控制一个对象是否激活
把游戏对象拖到左侧的槽位上,这里对一个Cube操作,右键Add Activation Clip,当时间处于Active片段内时会激活游戏对象,否则隐藏游戏对象,点击轨道左侧(红框范围),在Inspector上显示轨道相关属性
Activation Track是轨道的显示名称,Post-playback state表示Timeline播放完后游戏对象的状态
名称 | 描述 |
---|---|
Active | 播放完激活游戏对象 |
Inactive | 播放完后隐藏游戏对象 |
Revert | 游戏对象恢复到播放之前的激活状态 |
Leave As Is | 保持最后一帧的状态 |
点击时间轴上的片段,在Inspector上可以看到片段相关信息,片段的开始时间,结束时间,持续时间,分别以秒和帧为单位显示
点击🔒图标(快捷键M),会将轨道锁定,不能操作,这是为了防止误触,此时轨道还是生效的
点击👁图标(快捷键L),会将轨道禁用,此时轨道不生效,当有多条轨道时,可以禁用其中几条轨道,方便对其他轨道操作
Control Track
和 Activation Track 类似,控制对象是否激活,在一条轨道上可以控制多个对象是否激活,而 Activation Track 一条轨道只能控制一个对象是否激活,直接把场景中的对象拖动到时间线上即可
点击片段,查看相关设置
名称 | 描述 |
---|---|
Source Game Object | 场景中绑定的的游戏对象或prefab |
Control Activation | 勾选才会控制对象的激活状态 |
Control Playable Directors | 是否控制其他的Playable Director |
Control Particle Systems | 是否将控制粒子系统 |
Random Seed | 为粒子系统提供的随机种子 |
Control ITimeControl | 是否控制实现ITimeControl接口的Monobehaviours |
Control Children | 是否控制子对象中的粒子系统,Playable Director |
Audio Track
Audio Track控制声音播放,可以不用指定Audio Source,在时间线上右键Add From Audio Clip选择声音片段即可,也可以直接把声音片段拖到时间线上,拖动两个片段使其重叠,重叠部分(斜线部分)就是融合,会在两个片段之间做一个平滑过渡
点击上方Play按钮即可听到声音
点击声音片段,在Inspector界面上会显示片段相关属性
名称 | 描述 |
---|---|
Ease In Duration 和 Blend Out Duration | 控制过渡时间 |
Clip In | 设置片段从第几秒开始播放 |
Speed Multiplier | 设置播放速度倍速 |
Blend Curves | 过渡曲线控制融合时的变化速度,默认使用Auto,也可以切换到Manual受到控制曲线 |
Clip | 片段资源引用 |
Loop | 是否循环 |
Volume | 声音大小 |
Animation Track
控制游戏对象动画的播放
使用已有动画,首先要把场景中带有Animator的对象拖入槽位中,然后把这个对象相关的动画片段拖入时间线上,双击这个动画片段就可以打开Animation窗口,对动画做细致的调整
自己制作帧动画,先点击Start recording按钮进入编辑状态,拖动时间轴,修改对象身上的属性,此时这个动画片段是Infinite Clip,即无限长的片段,需要把它转换成有限长的片段
右键Convert To Clip Track就会把它转换成有限长片段
Signal Track
建立Timeline与外部系统的沟通渠道
Signal Asset 信号资源:用于发射器和接收器之间的联系,可以在多个Timeline实例中复用
Signal Emitter 信号发射器:包含对信号资源的引用,可以在Markers,Signal Track或其他轨道上添加
Signal Receive 信号接收器:设置触发的方法
在任意轨道的时间线上右键Add Signal Emitter,添加一个信号发射器
第一次添加会有感叹号提示没有信号资源,点击Create Signal 创建一个信号资源,点击Add Signal Receiver会在轨道绑定的物体上添加Signal Receiver组件
以后创建发射器就可以通过下拉列表来选择信号资源
名称 | 描述 |
---|---|
Retroactive | 表示如果Timeline的播放开始于Signal Emitter的时间之后,是否仍然触发信号 |
Emit Once | 为True表示在循环期间只发出一次此信号 |
在Signal Receiver上指定触发的方法,这里用一个简单的脚本进行测试
public class TimelineTest : MonoBehaviour
{
public void OnTimelineStart()
{
// 禁用输入
Debug.LogError("start");
}
public void OnTimelineEnd()
{
// 恢复输入
Debug.LogError("end");
}
}
这里创建两个信号资源Start Signal和End Signal,在Timeline的开始和结尾添加两个发射器,分别指定信号资源是Start Signal和End Signal,在接收器中设置相应方法,这个就可以在Timeline的开始和结束触发OnTimelineStart和OnTimelineEnd方法,游戏中播放Timeline时通常会禁止玩家的输入操作,可以在这两个方法中添加禁用和恢复的逻辑,这个方法最多带一个参数
点击轨道上的Track Markers可以展开或收起发射器
Playable Track 及自定义轨道
Timeline是由Track(轨道),Clip(片段),Behavior(行为),Mixer(混合器)四元素组成
Track | 每一行是一个轨道 |
---|---|
Clip | 轨道上的片段 |
Behavior | 片段在轨道上的行为逻辑 |
Mixer | 两个片段应该怎样融合 |
使用Playable Track实现自定义代码逻辑,至少需要定义Clip和Behavior这两个元素对应的脚本
右键 -> Create -> Playables 可以创建Clip和Behavior这两个元素的脚本模板,会自动填充一些常用方法,其中Playable Asset C# Script就是对应Clip
当Timeline开始播放时,会创建名为Playable的节点,Playable直译为可播放的,它是和时间有关的,如一段音乐,一段动画,一段Timeline,Timeline本身也是Playable可以嵌入到别的Timeline中。多个Playable被组织成一种树状结构,称为PlayableGraph。对于每一帧,Timeline都会对该图进行采样,以读取和混合多个数据源(动画、音频等),Mixer会根据每个Clip的权重去混合得到最后的结果
这里演示创建Clip和Behavior脚本来控制Light光照变化
using UnityEngine;
using UnityEngine.Playables;
[System.Serializable]
public class LightClip : PlayableAsset
{
// 由于PlayableAsset是个Asset资源,它不能直接引用场景中的对象
// 在PlayableAsset中,public修饰的引用类型,只可以选择Project中的对象
// ExposedReference暴露引用,允许在Hirearchy面板上引用场景中的灯光
public ExposedReference<Light> light;
public Color lightColor;
public float lightIntensity;
// Factory method that generates a playable based on this asset
public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
{
// 工厂方法创建playable,这个playable属于传入的graph
var playable = ScriptPlayable<LightBehaviour>.Create(graph);
// 获取这个LightBehaviour
var lightBehavior = playable.GetBehaviour();
// 将light变量解析为一个光源对象,graph.GetResolver()方法获取一个上下文对象,
// 然后根据这个对象的引用表来查找light变量对应的光源对象
lightBehavior.light = light.Resolve(graph.GetResolver());
lightBehavior.lightColor = lightColor;
lightBehavior.lightIntensity = lightIntensity;
return playable;
}
}
Timeline运行第1帧时会调用上面的CreatePlayable方法创建Playable对象,playable.GetBehaviour() 获取Behaviour并赋值就是克隆数据
// A behaviour that is attached to a playable
public class LightBehaviour : PlayableBehaviour
{
public Light light;
public Color lightColor;
public float lightIntensity;
// Called when the owning graph starts playing
public override void OnGraphStart(Playable playable)
{
// 获取这个playable关联的PlayableDirector组件
var playableDirector = playable.GetGraph().GetResolver() as PlayableDirector;
}
// Called when the owning graph stops playing
public override void OnGraphStop(Playable playable)
{
}
// Called when the state of the playable is set to Play
public override void OnBehaviourPlay(Playable playable, FrameData info)
{
if (light == null)
return;
light.color = lightColor;
light.intensity = lightIntensity;
}
// Called when the state of the playable is set to Paused
public override void OnBehaviourPause(Playable playable, FrameData info)
{
}
// Called each frame while the state is set to Play
public override void PrepareFrame(Playable playable, FrameData info)
{
}
//在片段上的每一帧调用,两个片段之间的空隙不会调用
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
// playable是Clip创建的
Debug.LogError("已播放时间:" + playable.GetTime() + " 持续时间" + playable.GetDuration());
// FrameData是帧信息,当需要这一帧的时间增量,可以使用 info.deltaTime
Debug.LogError("时间增量" + info.deltaTime);
// playerData 是绑定的对象
var go = playerData as GameObject;
if (go)
{
var light = go.GetComponent<Light>();
}
}
}
这样就可以在Playable Track上右键添加LightClip,开始运行时就会调整灯光的颜色和强度
上面的代码因为要引用场景中的灯光,所以在Clip中定义了参数变量,然后把变量传递给Behavior,如果只使用值类型变量,还有另一种写法,把Behavior序列化,作为Clip的成员变量,这里以TimeDilationTrack的相关代码为例
[Serializable]
public class TimeDilationBehaviour : PlayableBehaviour
{
public float timeScale = 1f;
}
[Serializable]
public class TimeDilationPlayableAsset : PlayableAsset
{
[NoFoldOut] // 移除折叠,并绘制所有的子属性
public TimeDilationBehaviour template = new TimeDilationBehaviour();
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
return ScriptPlayable<TimeDilationBehaviour>.Create(graph, template);
}
}
Clip 实现 ITimelineClipAsset 接口可以控制片段上显示的信息,可以使用 ClipCaps.All 来显示全部信息
[System.Serializable]
public class LightClip : PlayableAsset, ITimelineClipAsset
{
public ClipCaps clipCaps => ClipCaps.All;
//...
}
自定义轨道
自定义轨道LightTrack,并设置轨道只能添加LightClip类型的片段
using UnityEngine;
using UnityEngine.Timeline;
[TrackColor(20/255f, 200/255f, 50/255f)] //设置轨道前的颜色
[TrackClipType(typeof(LightClip))] //轨道能添加什么类型的片段
[TrackBindingType(typeof(GameObject))] //指定轨迹需要绑定到的对象类型
public class LightTrack : TrackAsset
{
}
自定义混合器
这里使用TimeDilationTrack相关代码说明,Mixer是在Track中创建的
[TrackColor(0.855f, 0.8623f, 0.87f)]
[TrackClipType(typeof(TimeDilationPlayableAsset))]
public class TimeDilationTrack : TrackAsset
{
// Creates a runtime instance of the track, represented by a PlayableBehaviour.
// The runtime instance performs mixing on the timeline clips.
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
{
return ScriptPlayable<TimeDilationMixerBehaviour>.Create(graph, inputCount);
}
}
创建混合器的Playable是铺满整个时间线的,包含那些没有片段的地方
Mixer也是PlayableBehaviour,也有ProcessFrame方法,在树形结构体中Mixer是Clip的父节点,会先调用Clip绑定的Behavior中的ProcessFrame方法(如有),然后调用Mixer中的ProcessFrame方法,如果片段需要混合,那只实现Mixer中的ProcessFrame方法即可
Mixer在ProcessFrame中遍历所有的Clip,并获取每个Clip的权重,根据权重混合得到最后的结果
如图,当Timeline播放到第一个Clip时,这个Clip的权重为1,后面两个Clip的权重为0
当播放到Clip2时(未混合),Clip权重为0,Clip2权重为1,Clip3权重为0
当播放到Clip2和Clip3混合时,Clip权重为0,Clip2权重 + Clip3权重 = 1
public class TimeDilationMixerBehaviour : PlayableBehaviour
{
private float m_DefaultTimeScale = 1;
// Called every frame that the timeline is Evaluated.
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
// inputCount表示这条轨道上有几个Clip
int inputCount = playable.GetInputCount();
float timeScale = 0f;
float totalWeight = 0f;
// blend clips together
for (int i = 0; i < inputCount; i++)
{
// 获取第i个Clip的权重
float inputWeight = playable.GetInputWeight(i);
ScriptPlayable<TimeDilationBehaviour> playableInput = (ScriptPlayable<TimeDilationBehaviour>)playable.GetInput(i);
TimeDilationBehaviour input = playableInput.GetBehaviour();
// 混合逻辑
timeScale += inputWeight * input.timeScale;
totalWeight += inputWeight;
}
// blend to/from the default timeline
Time.timeScale = Mathf.Max(0.0001f, Mathf.Lerp(m_DefaultTimeScale, timeScale, Mathf.Clamp01(totalWeight)));
}
// Called when the playable graph is created, typically when the timeline is played.
public override void OnPlayableCreate(Playable playable)
{
m_DefaultTimeScale = Time.timeScale;
}
// Called when the playable is destroyed, typically when the timeline stops.
public override void OnPlayableDestroy(Playable playable)
{
Time.timeScale = m_DefaultTimeScale;
}
}
Cinemachine Track
如果安装了Cinemachine,会有这个轨道控制Cinemachine相机之间的切换,场景中创建两个虚拟相机,分别看向Cube的左侧和右侧,把虚拟相机拖到时间线上自动生成片段
拖动两个片段使其重叠,重叠部分就是融合,它会对两个相机之间的属性做插值,做一个平滑过渡
Samples
在官方的案例中还有几个轨道可以用
TextTrack
TextTrack用于修改文本内容,可以做字幕,点击片段设置字色,字号,文本内容
修改Ease In Duration和Ease Out Duration增加淡入淡出效果
TimeDilationTrack
这个轨道修改 Time.timeScale,点击片段设置 timeScale 的值,运行到片段时会修改Time.timeScale的值,片段之外的地方恢复到默认值1
Time.timeScale 控制全局时间,会影响到动画,视频等,一般用于实现慢动作
Video Track
将视频片段直接拖到时间线上就行,重叠部分也有融合效果
名称 | 描述 |
---|---|
Video Clip | 视频片段引用 |
Mute | 是否静音 |
Loop | 是否循环 |
Preload Time | 视频开始预加载视频流之前的时间量 |
Aspect Ratio | 视频的长宽比 |
Render Mode | 视频内容将被绘制在哪里,相机的远剪裁面或近剪裁面 |
Target Camera | 指定要渲染到哪个相机,没有指定,则使用主相机 |
Audio Source | 指定一个可选的音源 |
Tween Track
设置对象在两个Transform之间位移,旋转
Should Tween Position 勾选表示改变指定对象的位置
Should Tween Rotation 勾选表示改变指定对象的旋转
插件 Default Playables
这是官方提供的免费插件,包含一些其他轨道,地址
LightControlTrack
这个轨道和上面实现的自定义轨道 LightTrack 类似,控制灯光颜色强度,实现灯光混合叠加效果,但一个轨道只能控制一个光源
TextSwitcherTrack
和上面案例中的 TextTrack 类似,可以做字幕
TimeDilationTrack
和上面案例中的 TimeDilationTrack 一样,实现慢动作
TransformTweenTrack
和上面案例中的 Tween Track 类似,控制对象的移动旋转
ScreenFaderTrack
控制图片的颜色渐变
NavMeshAgentControlTrack
控制物体在导航网格上移动,这里创建一个 Plane 烘焙网格
创建一个胶囊体添加 NavMesh Agent 组件作为需要移动的物体,创建一个空物体,用它 Transform 作为移动的终点
胶囊体放入轨道槽位,片段上引用目标位置
运行才能看到效果
Timeline Playable Wizard
这是帮助我们生成 Timeline 4 个元素的的工具
填写好轨道名称,设置轨道绑定类型,参数等就可以生成4个元素对应的脚本
PlayableGraph Visualizer
这是官方的一个可视化工具,显示 Timeline 或 Animator 中的树形结构
通过 Package Manager 安装,git 地址输入 https://github.com/Unity-Technologies/graph-visualizer.git
安装后在 Window -> Analysis 下会有入口
点开后会显示Timeline上每个轨道的相关信息
插件Material Timeline Track
这是资源商城的插件,提供了两个轨道,可以在 Timeline 上修改材质的属性,地址
Material Track
使用 Animation Track k动画时,可以记录数值类型,枚举类型的修改,但是贴图的修改不会记录下来
使用 Material Track 可以获取材质 Shader 中的所有属性进行修改
Renderer Track
这个轨道绑定含有 Renderer 组件的对象,只会修改绑定对象的材质属性,不会影响到相同材质的其他对象
参考
官网文档
通过实际案例演示学习Timeline
Playable API:定制你的动画系统文章来源:https://www.toymoban.com/news/detail-714941.html
Timeline Unity3d 教程文章来源地址https://www.toymoban.com/news/detail-714941.html
到了这里,关于Unity Timeline及其相关插件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!