# custom_timeline **Repository Path**: liuyaoif/custom_timeline ## Basic Information - **Project Name**: custom_timeline - **Description**: 扩展unity的timeline,实现自定义轨道(track)和clip。 - **Primary Language**: Unknown - **License**: WTFPL - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 3 - **Created**: 2021-12-31 - **Last Updated**: 2024-09-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: Unity ## README # Timeline扩展方案 > Timeline默认的Track和Clip如下。 > ![avatar](Document/TimelineTrack.png) > 如果想让Timeline驱动游戏逻辑,需要自定义TrackAsset,PlayableBehaviour和PlayableAsset 来实现。目前有3种方式使用自定义功能。 > || > |:----:| > |Playable track| > |ClipBehaviour| > |TrackBehaviour| > ## 1. Playable track方式 1. 添加一条Playable track。 ![avatar](Document/AddPlayableTrack.png)。 1. 创建一个PlayableAsset脚本: create->Playables->Playable Assets C# Script。 2. 拖到Playable track上。 > 这个方法受限制严重,不推荐使用。 ## 2. ClipBehaviour 1. 创建一个TrackAsset的C#脚本。 ```CSharp [TrackClipType(typeof(TextTLAsset))] [TrackBindingType(typeof(Text))] public class TextTLTrack : TrackAsset { /// /// TrackAsset在创建时必然会遍历所有的Clip,有机会给所有的clip传值 /// /// /// /// /// protected override Playable CreatePlayable(PlayableGraph graph, GameObject gameObject, TimelineClip clip) { PlayableDirector direct = graph.GetResolver() as PlayableDirector; //在Clip创建时传参 TextTLAsset asset = clip.asset as TextTLAsset; asset.Label = direct.GetComponent().label; return base.CreatePlayable(graph, gameObject, clip); } } ``` > TrackAsset实现CreatePlayable方法,这条Track上每一个Clip(拖拽一个Asset就有一个Clip)都会调用一次这个方法。利用这个方法给Asset传参数。这里传递了label这个控件。 2. 创建一个PlayableAsset的C#脚本。 ```CSharp [System.Serializable] public class TextTLAsset : PlayableAsset { public Text Label { set; get; } public string Content; /// /// 在创建时向Behaviour传引用 /// /// /// /// public override Playable CreatePlayable(PlayableGraph graph, GameObject go) { //创建ClipBehaviour var playable = ScriptPlayable.Create(graph); var behaviour = playable.GetBehaviour(); behaviour.Label = Label; behaviour.Content = Content; return playable; } } ``` > PlayableAsset实现CreatePlayable方法,并Create一个PlayableBehaviour,这个Behaviour的生命周期是绑定这个Asset的。也就是说有多个Clip就有多少Behaviour实例,所以称之为ClipBehaviour。Asset向自己的Behaviour传参Label控件和Content参数。 3. 创建一个PlayableBehaviour的C#脚本。 ```CSharp [Serializable] // A behaviour that is attached to a playable public class TextTLBehaviour : PlayableBehaviour { public Text Label; public string Content; public override void OnBehaviourPlay(Playable playable, FrameData info) { if (Label != null) { Label.text = Content; } } public override void OnBehaviourPause(Playable playable, FrameData info) { if (Label != null) { Label.text = string.Empty; } } } ``` > Behaviour实现OnBehaviourPlay和OnBeahviourPause两个方法,当时间线走到对应的Asset时就会调用到。 > ![avatar](Document/ClipBehaviour.png) > 这个方案适合于做连续台词等不需要混合的需求。 ## 3. TrackBehaviour > TrackBehaviour方式和ClipBehaviour大部分相似,也是需要自定义的TrackAsset,PlayableBehaviour和PlayableAsset。区别在于PlayableBehaviour由TrackAsset创建而不是Asset。 1. 创建TrackAsset ```CSharp [TrackClipType(typeof(ColorTLAsset))] [TrackBindingType(typeof(Text))] public class ColorTLTrack : TrackAsset { public ScriptPlayable TrackBehaviourPlayable; private ColorTLBehaviour behaviour; //创建Track混合器而不是Clip public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) { //取外部引用 PlayableDirector direct = graph.GetResolver() as PlayableDirector; Text label = direct.GetComponent().label; //创建TrackBehaviour并设置inputCount,inputCount就是Clip的个数 TrackBehaviourPlayable = ScriptPlayable.Create(graph); TrackBehaviourPlayable.SetInputCount(inputCount); behaviour = TrackBehaviourPlayable.GetBehaviour(); //传递参数 behaviour.label = label; behaviour.track = this; return TrackBehaviourPlayable; } } ``` > 注意,TrackBehaviour是TrackAsset创建,生命周期绑定到了TrackAsset上,当Track启动、结束后触发Behaviour的OnBehaviourPlay和OnBeahviourPause,这个Behaviour和Clip是没有关系的。 2. 创建PlayableAsset ```CSharp [System.Serializable] public class ColorTLAsset : PlayableAsset { public Color CurColor; public override Playable CreatePlayable(PlayableGraph graph, GameObject go) { return Playable.Create(graph); } } ``` > TrackBehaviour方案的Asset比较简单,只是暴露参数用于设置就好了。 3. 创建PlayableBehaviour ```CSharp public class ColorTLBehaviour : PlayableBehaviour { public Text label; public ColorTLTrack track; //OnBehaviourPlay和OnBehaviourPause方法和Clip没关系了,所以只能在ProcessFrame(Update)中获取 public override void ProcessFrame(Playable playable, FrameData info, object playerData) { //取ClipCount int clipCount = playable.GetInputCount(); int index = 0; for (int i = 0; i < clipCount; i++) { float weight = playable.GetInputWeight(i); //Weight > 0f的Clip是进入了的Clip,可能有多个 if (weight > 0f) { index = i; break; } } //根据Clip的Index取Clip和Asset ColorTLAsset curAsset = null; foreach (var itr in track.GetClips()) { if (index == 0) { curAsset = itr.asset as ColorTLAsset; } index--; } //赋值 if (label != null) { label.color = curAsset.CurColor; } } } ``` > 该方法适合自动控制有融合的多个Clip之间的混合。[Timeline混合Demo](https://blogs.unity3d.com/2018/09/05/extending-timeline-a-practical-guide/)