Table of Contents of Series Articles
Custom TimeLine
Preface
Custom TimeLine is actually a custom track. Here we implement a simple example. The Unity version I use is
a URP project created in 2021.3.20f1c1. In fact, Build-in is the same, but some codes may need to be changed.
text
Here we first introduce the implementation idea, because what we want to achieve is the effect of the lyrics below every time we watch the music channel. First, we need to create two Texts, one below, as the background color, and then control the words on the upper layer to move. Achieve the desired effect
UI part
The Text I created using TMP has the structure as shown below
One of the places that needs to be highlighted is the Mask. This is an empty object hung on the Rect. The Mask 2D component is used to block text to achieve effects. If you do not use a mask but directly control the Text, the text will be stuck. In order to avoid this The phenomenon is so masking is used.
There is also the need to set the center point to (0, 0)
and create an empty object and add the Playable Director component to control the timeline.
code part
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);
}
}
}
controlled object
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);
}
}
Summarize
That’s basically it. Because this is just a simple example, I won’t go into too much detail. Because it is actually very simple as long as you understand the principle.