Customize TimeLine to implement karaoke track

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

Insert image description here

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)
Insert image description here
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);
    }
}

Insert image description here
Insert image description here

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.

Guess you like

Origin blog.csdn.net/m0_52021450/article/details/132640052