Overview

we needed a dialogue system for our cutscenes—something that works well with Unity’s Timeline and supports easy localization.

Features

https://drive.google.com/file/d/1AhOkXB4tt9EMWq55XRHz3GCjn9yRbSHs/view?usp=sharing

Timeline

using UnityEngine;
using UnityEngine.Playables;

public class DialogueClip:PlayableAsset
{
    public int dialogueId;
    public ExposedReference<mono_DialogueBoxController> dialogueBox;

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var playable = ScriptPlayable<DialogueBehavior>.Create(graph);

        DialogueBehavior dialoguePlayable = playable.GetBehaviour();
        dialoguePlayable.dialogueId = dialogueId;
        dialoguePlayable.dialogueBox = dialogueBox.Resolve(graph.GetResolver());

        return playable;
    }

}
using UnityEngine.Playables;

public class DialogueTrackMixer:PlayableBehaviour
{
    private int _currentInput=-1;

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        mono_SceneDialogueMgr text = playerData as mono_SceneDialogueMgr;
        int current_id=-1;
        float current_alpha = 0;

        if (!text) return;

        int inputcount=playable.GetInputCount();

        for (int i=0;i<inputcount;i++)
        {
            float inputWeight=playable.GetInputWeight(i);

            if (inputWeight>0)
            {
                ScriptPlayable<DialogueBehavior> inputPlayable=(ScriptPlayable<DialogueBehavior>)playable.GetInput(i);
                DialogueBehavior input=inputPlayable.GetBehaviour();
                if (_currentInput != i)
                {
                    _currentInput = i;
                    current_id = input.dialogueId;
                    text.SetDialogue(current_id, input.dialogueBox);
                }

                current_alpha = inputWeight;

            }
        }
        text.SetAlpha(current_alpha);

        
    }
}

Monobehaviour

public interface IDialogueBox {
    public void SetText(string str);
    public void SetAlpha(float alpha);
    public void SetFont(TMP_FontAsset font);
    public void Show();

    public void Hide();
}
using TMPro;
using UnityEngine;

public class mono_DialogueBoxController : MonoBehaviour,IDialogueBox
{
    [SerializeField] private TextMeshProUGUI _txt;
    [SerializeField] private TransitionEffect _transition;

    private float _charctersCount=0;

    public void SetAlpha(float alpha)
    {
        switch (_transition)
        {
            case TransitionEffect.None:
                _txt.alpha = 1;
                setVisible(99999);
                break;
            case TransitionEffect.Alpha:
                _txt.alpha = alpha;
                setVisible(99999);
                break;
            case TransitionEffect.Typing:
                _txt.alpha = 1;
                setVisible(Mathf.CeilToInt(_charctersCount*alpha));
                break;
            default:
                break;
        }
        
    }

    public void SetText(string str)
    {
        _txt.text = str;
        _charctersCount=str.Length;
    }

    public void SetFont(TMP_FontAsset font)
    {
        _txt.font = font;
    }

    private void setVisible(int visibleCharacter)
    {
        _txt.maxVisibleCharacters = visibleCharacter;
    }

    public void Hide()
    {
        gameObject.SetActive(false);
    }

    public void Show()
    {
        gameObject.SetActive(true);
    }

    public enum TransitionEffect
    {
        None,
        Alpha,
        Typing
    }
}