we needed a dialogue system for our cutscenes—something that works well with Unity’s Timeline and supports easy localization.
https://drive.google.com/file/d/1AhOkXB4tt9EMWq55XRHz3GCjn9yRbSHs/view?usp=sharing
DialogueTrack inherits from TrackAsset, defining a custom timeline track asset.DialogueClip inherits from PlayableAsset, defining a timeline clip asset. It overrides CreatePlayable(PlayableGraph graph, GameObject owner) to pass the dialogue ID and optionally a customized dialogue box.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;
}
}
DialogueTrackMixer inherits from PlayableBehaviour and overrides ProcessFrame(Playable playable, FrameData info, object playerData) to manage smooth transitions between dialogue clips.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);
}
}
mono_DialogueBoxController is an implementation of IDialogueBox. It manages dialogue box display using TextMeshProUGUI and supports three transition effects: None, Alpha, and Typing.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
}
}
mono_SceneDialogueMgr bridges the timeline, database, and dialogue box systems. Invoked by the timeline, it retrieves dialogue text using the dialogue ID and selected language, then delivers it to the appropriate dialogue box instances.