Timeline

Timeline

Track一览

名称 说明
Track Group Track组,可以放多个track,可以用来按组分类划分
Activation Track 用来控制GameObject是否激活
Animation Track 用来控制Animation的播放
Audio Track 用来控制Audio的播放
Control Track 用来控制gameobject
Signal Track 用来发射信号,出发事件
Playable Track 用户自定义的轨道

Control Track

用来控制prefab、特效、gameobject等的时间线

这个Control Track​可以拖入其他director,然后就能调整这个director的播放,形成嵌套效果

注意:

  1. 在clip外会自动销毁,
  2. 因此拖入了director后不能拖入director控制的其他gameobject,因为在gameobject外自身是被销毁的状态

在track中的每一个物体,都对应一个clip来控制

参数

通用属性跳过,看两眼就知道怎么用了

SourceGameObject:此 clip 要控制的物体

Prefab:此clip要生成并控制的prefab,当这里赋予了一个Assets下的prefab时,SourceGameObject会变成ParentObject,ParentObject指定的物体将为Prefab生成时的父物体。

ControlActivation:

  • 控制激活,控制SourceGameObject的激活状态,
  • 不勾选SourceGameObject将保持自有状态(也就是会一直存在或者隐藏,取决于自己)

PostPlayback:剪辑播放完成时SourceGameObject的状态

  • Active :剪辑播放完后,SourceGameObject.active=true
  • ​​Inactive:剪辑播放完后,SourceGameObject.active=false
  • Revert:剪辑播放完后,SourceGameObject.active=播放前的active的值

Advanced 高级选项:

  1. ControlPlayableDirectors:控制物体上的 timline 播放状态,勾选后可以控制 clip 物体上的播放进度
  2. ControlParticleSystem:控制粒子发射器,不勾选只能控制 clip 物体的显隐,勾选后可以 clip 物体上的粒子发射器的发射进度,可以实现粒子发射的倒放
  3. RandomSeed:当粒子系统的 seed 设置为 AutoRandomSeed 时,这里的值可以设置粒子系统的随机种子,这个选项仅对ps的clip生效,对于 clip 是 timeline 类型的不生效
  4. ControlItimeControl:勾选后可以同步当前 timeline 的时间到 clip 物体上继承了 ItimeControl 接口的组件上
  5. ControlChildren:勾选后可以控制 Clip 物体的子对象内的 timeline 、粒子系统和继承了ItimeControl 接口的实体

ControlTrack clip的操作

  • ControlTrack Clip 遵循通用的 clip 操作
  • ControlTrack Clip 中间无法做混合,只能做切除操作

Signal Track

Unity【Timeline】- 使用Signal Track添加事件_unity timeline 事件-CSDN博客

因为signal是具体到某个物体上的,需要物体具有signal receiver组件,因此,对于某些额外的物体只需要使用signal功能,就可以采用signal track而不用signal receiver组件

Annotation

注释标记示例 |时间线 |1.7.5 —- Annotation marker sample | Timeline | 1.7.5 (unity.cn)

书签,用来作为注释和标记

Timeline Clip编辑模式

Timeline的Clip有三种不同的编辑模式,分别是Mix模式(混合模式,默认),Ripple模式(波纹模式),Replace模式(替换模式)

点击上图中的几个按钮,就可以切换不同的模式,一次是Mix模式,Ripple模式,Replace模式。

还有一种方法是临时切换模式,快速编辑的时候很有用:比如你编辑一个clip的时候想临时切换到Ripple模式,就可以使用快捷键临时切换,而不用切来切去了。切换方法如下:

  • 按住1​临时切换到Mix模式。
  • 按住2​临时切换到Ripple模式。
  • 按住3​临时切换到Replace模式。

注意是按住这些键,并同时操作。

Mix模式

默认的编辑模式。使用这种模式时,当你拖动clip,两个clip发生重叠时,会将重叠部分混合。

在Mix模式下,当光标在clip的不同区域拖拽时,光标会有不同的变化,表示会执行不同的功能。

  • 在clip的最前面时,光标会变成一个修剪的光标,拖拽可以修改clip自身开始播放的位置。(注意不是在Timeline中开始播放的位置,而是clip自身开始播放的时间,比如clip有5秒,可以修改为从第3秒开始播放。)
  • 在clip中间时,光标会变成一个移动的光标,此时拖拽可以移动clip。
  • 在clip最后面时,光标会变成一个修剪的光标,拖拽可以修改clip自身结束播放的位置。

在Mix模式中,如果拖拽时和其他clip发生重叠,光标会变成一个白色箭头,指示混合的位置。箭头有三种情况,指示混合创建的位置,在开头、结尾、或是开头和结尾都有。

Ripple模式

使用这种模式时,调整clip的长度和位置时,后面的clip的相对位置保持不变。

在Ripple模式下,当你修剪或者移动一个clip时,光标会变成一个黄色的箭头,表示影响后面的clip。一个黄色的竖线,代表ripple开始的点。

Replace模式

替换模式。使用这种模式时,当两个clip发生重叠时,当前操作的clip会替换掉重叠的部分,不会发生混合。

注意重叠的部分被自动覆盖以后,再修改当前操作的clip的长度后,被覆盖的那个clip也不会自动复原,需要操作被覆盖的clip来还原。

Signal介绍

信号,是timeline触发事件的媒介,因为其具有广播的性质,所以比event的名字更适合

如何添加信号

  1. 右击任何一个bindingType是GameObject或者Component的Track,在弹出的菜单栏中点击Add Signal Emitter即可添加信号

  1. 信号添加好后,会出现下图中的游标,带警告的游标说明没有选择要触发的信号类型(Emit Signal为none)

3 选中Signal游标,在检视版中选择触发的信号类型

  1. Signal选好后,需要在下方添加一个Signal Receiver用来选择接收信号的方法,同按钮点击事件,不在赘述

  1. 至此当timeline播放到signal游标处就会触发对应的事件了,(注意,signal触发的事件,只有signal所在track上的对象上的signal receiver生效)

如何添加带参信号

  1. 继承SignalEmitter,实现一个新的信号触发器,并在其中加入新的参数

  1. 添加自定义的信号。当创建了新的SignalEmitter时,timeline会在原添加信号菜单处加入添加新信号的菜单

  1. 选择信号类型同普通信号。

  2. signal receiver需要自己实现,在挂在track的对象上,这个时候就可以通过 notification获取带参信号的参数了!

自定义

timeline很强大,除了自带的轨道,还可以自己定义轨道,从而能够根据自身需要添加timeline clip

自定义clip:Playable Track

创建自定义clip需要2个脚本

  • 一个用于存放数据:需要继承PlayableAsset
  • 一个用于处理逻辑:需要继承PlayableBehaviour

存放数据的脚本,也是显示在Playable Track​的脚本

这个脚本必须继承自`PlayableAsset`​

这个脚本的public成员,会序列化显示在对应的Inspector上,以便进行配置

必须重写抽象方法`CreatePlayable`​,这个方法返回一个`Playable`​类对象,在这个方法中可以传递配置好的成员

处理逻辑的脚本,我们可以重写多个生命周期函数,以进行调用

以text脚本为例,我们可以写成如下形式,在TextPlayableAsset​中配置数据,然后传到TextPlayableBehaviour​进行逻辑处理

逻辑处理的部分如下

为了获得这些数据,我们在TextPlayableAsset​中配置数据,再传递到TextPlayableBehaviour

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class TextPlayableAsset : PlayableAsset
{
//配置的数据
public ExposedReference<TextMeshProUGUI> textMeshPro;
public Color color = Color.white;
public int fontSize = 14;
public string text = "";

public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
TextMeshProUGUI textMeshProUGUI = textMeshPro.Resolve(graph.GetResolver());

ScriptPlayable<TextPlayableBehaviour> playable = ScriptPlayable<TextPlayableBehaviour>.Create(graph);

TextPlayableBehaviour playableBehaviour = playable.GetBehaviour();

playableBehaviour.textMeshPro = textMeshProUGUI;
playableBehaviour.color = color;
playableBehaviour.fontSize = fontSize;
playableBehaviour.text = text;

return playable;
}
}

/// <summary>
/// 逻辑处理:将指定的text格式配置给指定的TextMeshProUGUI
/// </summary>
public class TextPlayableBehaviour : PlayableBehaviour
{
public TextMeshProUGUI textMeshPro;
public Color color = Color.white;
public int fontSize = 14;
public string text = "";

//clip开始时执行
public override void OnBehaviourPlay(Playable playable, FrameData info)
{
textMeshPro.color = color;
textMeshPro.fontSize = fontSize;
textMeshPro.text = text;
}
}

ExposedReference类

在上面创建playable的相关脚本中,如果使用了继承自MonoBehaviour的字段,那么需要注意的是,

  1. Unity 的 Asset 只能引用资源对象,不能引用MonoBehaviour对象(场景中的对象)
  2. Unity 的 MonoBehaviour对象既可以引用资源对象,又可以引用MonoBehaviour对象

因此会出现场景中的物体不能拖拽,而预制体可以拖拽的情况

Unity 提供 ExposedReference 和 IExposedPropertyTable 机制来实现 Asset 引用场景中的对象

TextMeshProUGUI​为例,假设有字段

1
public ExposedReference<TextMeshProUGUI> textMeshPro;

在继承自PlayableAsset​的脚本中,可以在CreatePlayable​方法中这样处理

1
2
3
4
5
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
//解析ExposedReference
var textMeshProUGUI = textMeshPro.Resolve(graph.GetResolver());
}

在继承自PlayableBehaviour​的脚本中,可以这样处理

1
2
3
4
5
public override void OnGraphStart(Playable playable)
{
//获取解析器并解析,检索分配的控制对象
var _textMeshPro = textMeshPro.Resolve(playable.GetGraph().GetResolver());
}

Playable Track的改进

要实现Playable Track​,需要写两个脚本,一个是用来配置数据的,一个是用来处理逻辑的

但实际书写时,就会发现很多不便,因为我们需要在两个脚本中都写上同样的成员变量,再进行传递

我们可以利用[serializable]​特性直接进行成员传递,让继承自PlayableBehaviour​的脚本的成员出现在inpector上

上面的例子可以改成如下

如此,我们可以进行间接配置,从而略去中间的传递数据的过程

自定义轨道

使用player track,我们可以更改许多自定义的东西,比如text, transform。但是,player track只能创建clip,我们需要在每一个clip上绑定对应数据,如果我们希望对同一个东西进行频繁修改的话,创建的每一个clip都绑定到了同样的对象上

通过自定义轨道,能够让数据绑定到轨道上,这样,每一个clip就无需再绑定数据了

要自定义新轨道,需要继承自TrackAsset​,这个类里面可以什么都不写,如果要实现混合需要酌情重载CreateTrackMixer​和GatherProperties​方法

要拿到绑定的数据,需要在TextPlayableBehaviour​类中重写方法ProcessFrame​,使用playerData即可

1
2
3
4
5
6
7
8
9
10
11
12
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
var textMeshProUGUI = playerData as TextMeshProUGUI;

if (textMeshProUGUI == null)
return;


textMeshProUGUI.color = color;
textMeshProUGUI.fontSize = fontSize;
textMeshProUGUI.text = text;
}

这个时候右击timeline的菜单中就出现自定义的轨道了

【Unity学习笔记】ExposedReference类的初识 + 自定义Timeline轨道初识-CSDN博客

TimelineMixer

可以这么理解,Mixer是整条track的底层,它用来处理不同clip之间的混合,包括那些空白的部分的状况(是沿用最后的非空白的状态还是回到默认的状态)

要实现Mixer,需要另写一个继承自PlayableBehaviour​的脚本,然后在TrackAsset​中实现CreaterTrackMixer​方法,并绑定到这个脚本

  1. 在这个Mixer脚本中,也需要实现ProcessFrame​方法,并且Mixer的优先级更高,是覆盖执行。也就是说,当Mixer脚本中的重写了ProcessFrame​方法,此前的脚本也重写了ProcessFrame​方法,Mixer脚本中的ProcessFrame​方法会后调用
  2. 需要注意的是,某个clip的ProcessFrame​方法只在播放到这个clip时才启用,而Mixer脚本中的ProcessFrame​方法在整个timeline中都会执行
  3. Mixer脚本是不知道当前播放到哪里,它只能遍历全部的clip(空白的不管),查询其权重,如果clip返回的权重是1,它才会知道此时播放到这个clip
  4. 如果两个clip重叠,那么过渡的过程中,前面的clip返回的权重就会从1渐变到0,后面的clip返回的权重会从0渐变到1

还是以卡拉OK为例,之前的做法,在两个clip之间,歌词会沿用上一个clip的歌词,现在我们希望空白部分的歌词为空(最快的做法其实是直接创建clip替代空白,然后歌词不填)

TrackAsset​中实现CreaterTrackMixer​方法

实现Mixer脚本,因为两个clip在设计上是不会重叠的,所以不用管插值的部分,而每个clip自己实现了显示歌词的方法,那么在这个脚本里,我们只需要判断是不是当前没有播放到任何一个clip中,是的话就将歌词设置为默认值即可

实战:卡拉OK轨

来源:Timeline 3 | 卡拉OK轨 | 自定义轨道 | Unity3d 教程_哔哩哔哩_bilibili

要实现卡拉OK轨,首先要弄明白它的原理

我们可以使用两个叠加的歌词,一个白色,一个绿色,设置二者的轴心都在左侧边缘,然后将绿色歌词的TextMeshPro组件中的,wrapping设置为disabled,将overflow设置为截断,wrapping启用时,会自动换行,overlfow则是对溢出的处理

然后修改绿色歌词的RectTransform组件的宽度即可实现想要的功能

然后就是书写代码,我们使用四个脚本来实现

表现

1716864118552

注意:这里的显示其实是一个字符一个字符显示的,更好的滑动效果是逐渐显示,可以使用Rect Mask 2D​组件来实现,不控制TextMeshPro转而控制这个组件的属性即可

参考

官方文档:关于时间轴 |时间线 |1.7.5 —- About Timeline | Timeline | 1.7.5 (unity.cn)

翻译:Unity - Timeline 知识汇总_unity2020 timeline-CSDN博客

【Unity】TimeLine系列教程——编排剧情! - 知乎 (zhihu.com)

Unity Timeline扩展研究之基础篇(一) - 知乎 (zhihu.com)


Timeline
https://enlight3n.github.io/2024/05/24/UnityPackages/Timeline/
作者
Enlight3n
发布于
2024年5月24日
许可协议