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()); }