系列文章目录
自定义TimeLine
自定义TimeLine
- 系列文章目录
- 前言
- 正文
- UI部分
- 代码部分
- Data(数据)
- Clip(片段)
- Track(轨道)
- Mixer(混合)
- 被控制物体
- 总结
前言
自定义TimeLine实际上就是自定义轨道, 在这里我们实现一个简单的例子,我使用的Unity版本是2021.3.20f1c1
创建的一个URP项目。其实Build-in也是一样的 但是有的代码可能需要改一下。
正文
在这里先介绍一下实现思路,因为要实现的是我们每次收看音乐频道的时候下方歌词的效果,首先我们需要创建两个Text一个在下面,作为底色,然后在控制上层的字进行移动以达到效果
UI部分
我使用TMP创建的Text,其中的结构如下图
其中有一个地方需要着重说一下就是 Mask 这是一个 空物体挂在了Rect Mask 2D 组件 用于遮挡文字实现效果,如果不使用遮罩而是直接控制Text会出现文字卡顿的现象为了避免这种现象所以使用的是遮罩。
还有就是需要把中心点设为(0,0)
还有就是创建一个空物体加上Playable Director 组件控制timeline。
代码部分
Data(数据)
using UnityEngine.UI;
using UnityEngine.Playables;public class TextBehaviour : PlayableBehaviour
{public string line; //我们要显示的文字public float speed; // 文字移动的速度
}
Clip(片段)
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;public class TextClip : PlayableAsset,ITimelineClipAsset
{private TextBehaviour template;//这俩个参数是参数,不需要进行拖拽操作所以没有使用再上一篇讲的暴露变量public float speed;public string Line;public override Playable CreatePlayable(PlayableGraph graph, GameObject owner){var playable = ScriptPlayable<TextBehaviour>.Create(graph, template);TextBehaviour clone = playable.GetBehaviour();clone.speed = speed;clone.line = Line;return playable;}public ClipCaps clipCaps => ClipCaps.All;
}
Track(轨道)
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;[TrackBindingType(typeof(TextController))]
[TrackColor(255/255f,255/255f,200/255f)]
[TrackClipType(typeof(TextClip))]
public class TextTrack : TrackAsset
{public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount){return ScriptPlayable<TextMixer>.Create(graph, inputCount);}
}
Mixer(混合)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;public class TextMixer : PlayableBehaviour
{private string defaultLine = default;private float defaultProgress = default;public override void ProcessFrame(Playable playable, FrameData info, object playerData){var textController = playerData as TextController;int inputCount = playable.GetInputCount();string currentLine = defaultLine;float currentProgress = defaultProgress;bool isEmpty = true;for (int i = 0; i < inputCount; i++){var clipPlayable = (ScriptPlayable<TextBehaviour>)playable.GetInput(i);// 获取当前的 TextBehaviour behaviour = clipPlayable.GetBehaviour();float inputWight = playable.GetInputWeight(i);Debug.Log(inputWight);if (inputWight > 0){isEmpty = false;float progress = (float)(clipPlayable.GetTime() / clipPlayable.GetDuration());if(textController) textController.OnUpdate(behaviour.line,behaviour.speed,progress);}//textController.OnUpdate(defaultLine,0,defaultProgress);}if (isEmpty){textController.OnUpdate(defaultLine,0,defaultProgress);}}
}
被控制物体
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;public class TextController : MonoBehaviour
{public TextMeshProUGUI baseText;public TextMeshProUGUI colorText;[SerializeField]private RectTransform maskTransform;public void OnUpdate(string line,float speed,float progress){baseText.text = line;colorText.text = line;float x = colorText.preferredWidth * progress * speed;maskTransform.sizeDelta = new Vector2(x, maskTransform.sizeDelta.y);}
}
总结
基本上说完了,因为这个只是做一个简单示例所以也没有过多的细讲。因为只要理解了原理这其实很简单的。