0%

TimeLine自定义轨道

Unity中的TimeLine支持自定义轨道,一般需要新建三个(若需要处理混合则为四个)类。官方教学视频

一、Track

1、用途

首先需要定义一个轨道类,继承TrackAsset,它代表了时间轴内的轨道。官方API

2、代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[TrackColor(0.055f, 0.03f, 0.387f)]
[TrackClipType(typeof(MyClip))]
[TrackBindingType(typeof(Animator))]
public class MyTrack : TrackAsset
{
[SerializeField] int blendingDuration = 200;

protected override Playable CreatePlayable(PlayableGraph graph, GameObject gameObject, TimelineClip clip)
{
var asset = clip.asset as MyClip;
asset.duration = blendingDuration;
return base.CreatePlayable(graph, gameObject, clip);
}
}

3、轨道类可以被三种特性标签修饰

  • [TrackColor(float r, float g, float b)]用于定义轨道的颜色,方便不同轨道之间的区分;
  • [TrackClipType(Type clipClass)]用于指定在轨道中可创建的PlayableAsset类型,可以理解实现了轨道类型和片段类型之间的绑定,同一个轨道可以添加多种不同的片段类型,及可以有多个TrackClipType修饰同一个轨道类;
  • [TrackBindingType(Type type)]用于指定轨道需要绑定到的对象类型,如示例中的LookAtTrack是用于控制某个角色上的头部动画,因此需要绑定一个角色的Animator组件。若改轨道不需要绑定特定对象,则不需要添加该标签。

4、常用方法

  • protected override Playable CreatePlayable(PlayableGraph graph, GameObject gameObject, TimelineClip clip)
  • protected override void OnCreateClip(TimelineClip clip) 在新建片段时调用用于设置Clip的默认值。
  • public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)当片段之间支持混合时可添加该方法。

二、Asset

1、用途

接着定义一个继承PlayableAsset、实现接口ITimelineClipAsset的类,用于表示片段资源,该类中可以定义片段包含的字段,这些字段会暴露到Inspector中。

2、代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MyClip : PlayableAsset, ITimelineClipAsset
{
public string content;
public ExposedReference<Transform> target;

public DialogueBehaviour template = new MyBehaviour();

public ClipCaps clipCaps
{
get { return ClipCaps.None; }
}

public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
var playable = ScriptPlayable<MyBehaviour>.Create(graph, template);
var myBehaviour = playable.GetBehaviour();
myBehaviour.content = content;
myBehaviour.target = target;
return playable;
}
}

3、常用方法

通常该类中会重写CreatePlayable()方法,常用于实现该类和Behaviour类之间的数据传递,关于

ScriptPlayable 和 PlayableBehaviour的使用可参考ScriptPlayable 和 PlayableBehaviour - Unity 手册

三、Behaviour

1、用途

接着定义一个Behaviour类继承PlayableBehaviour用于描述片段中触发的行为。官方API

2、代码示例

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
public class MyBehaviour : PlayableBehaviour
{
private bool clipPlayed = false;
private bool pauseScheduled = false;
private PlayableDirector director;

public override void OnPlayableCreate(Playable playable)
{
director = (playable.GetGraph().GetResolver() as PlayableDirector);
}

public override void OnBehaviourPlay(Playable playable, FrameData info)
{
if (!clipPlayed && info.weight > 0f)
{
if (Application.isPlaying) pauseScheduled = true;
clipPlayed = true;
}
}

public override void OnBehaviourPause(Playable playable, FrameData info)
{
if (pauseScheduled)
{
pauseScheduled = false;
clipPlayed = false;
director.Pause();
}
}
}

3、常用方法

  • PrepareFrame 循环播放刷新时调用
  • OnBehaviourPlay 进入该行为片段时调用
  • OnBehaviourPause 退出该行为片段时调用
  • OnPlayableCreate 创建时、编辑器模式选中Timeline时
  • OnGraphStart 创建后、播放时
  • OnGraphStop 停止时,编辑器模式选中其他对象时
  • OnPlayableDestroy 同上,在停止后调用

四、Mixer

若需要使轨道片段支持融合,则需要添加Mixer类,该类同样继承PlayableBehaviour

五、踩坑合集

  • Clip的遍历:Timeline没有提供快速定位到某一Clip的接口,要想定位只能遍历,而且要从轨道开始遍历,这让代码写起来非常恶心,需要嵌套多层循环。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
IEnumerable<TimelineClip> tempClips = null;
var playableAsset = director.playableAsset as TimelineAsset;
foreach (var track in playableAsset.GetOutputTracks())
{
if (track is MyTrack && !track.muted)
{
tempClips = track.GetClips();
foreach (var clip in tempClips)
{
if (clip.asset is MyClip b)
{
//...
}
}
}
}
  • 对场景中对象的引用需要通过ExposedReference<T>创建,否则绑定完成的引用无法被Unity保存。对应的调用则需要通过Resolve(graph.GetResolver())解析出对象。
1
2
3
4
5
6
public ExposedReference<Transform> target;

public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
var target = target.Resolve(graph.GetResolver());
}