119 lines
3.1 KiB
C#
119 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using FMOD.Studio;
|
|
using UnityEngine;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
|
|
#endif
|
|
|
|
[CreateAssetMenu(menuName = "KernelPanic/Dialogue/Dialogue System")]
|
|
public partial class DialogueSystem : ScriptableObject
|
|
{
|
|
[SerializeField] private DialogueSettings _settings;
|
|
|
|
// https://stackoverflow.com/questions/2282476/actiont-vs-delegate-event
|
|
public event EventHandler<DialogueLine> onDialogueLine;
|
|
|
|
private readonly Dictionary<string, string> _fmodKeyCache = new Dictionary<string, string>();
|
|
// a list of dialogue keys that have already been spoken
|
|
private readonly List<string> _usedKeys = new List<string>();
|
|
|
|
private void OnEnable()
|
|
{
|
|
_fmodKeyCache.Clear();
|
|
_usedKeys.Clear();
|
|
|
|
// cache all dialogue keys for FMOD at start to avoid allocations later
|
|
foreach (var key in DialogueDatabase.Keys)
|
|
{
|
|
_fmodKeyCache[key] = $"{_settings.FMODPrefix}{key}";
|
|
}
|
|
}
|
|
|
|
// noRepeat locks this key off from further use. further attempts to use the key will be discarded
|
|
public void PlayLine(string key, bool noRepeat = true)
|
|
{
|
|
if (noRepeat)
|
|
{
|
|
if (_usedKeys.Contains(key)) return;
|
|
|
|
_usedKeys.Add(key);
|
|
}
|
|
|
|
// retrieve cached key
|
|
var fmodKey = _fmodKeyCache[key];
|
|
|
|
EventDescription? eventDescription = null;
|
|
|
|
try
|
|
{
|
|
eventDescription = FMODUnity.RuntimeManager.GetEventDescription(fmodKey);
|
|
}
|
|
catch (FMODUnity.EventNotFoundException e)
|
|
{
|
|
Debug.LogWarning($"no FMOD event {fmodKey}");
|
|
}
|
|
|
|
DialogueLine dl;
|
|
dl.text = DialogueDatabase.ReadDialogue(key);
|
|
// default duration to show ui elements for
|
|
dl.duration = _settings.HideAfter;
|
|
|
|
// read audio data out of FMOD, check if event exists
|
|
if (eventDescription.HasValue)
|
|
{
|
|
// assign values and play audio
|
|
|
|
// get dialogue line duration from FMOD
|
|
eventDescription.Value.getLength(out int ms);
|
|
|
|
// get length gives us a value in milliseconds so it needs to be converted to seconds
|
|
// before assignment
|
|
dl.duration = ms / 1000f;
|
|
|
|
// event is valid
|
|
FMODUnity.RuntimeManager.PlayOneShot(fmodKey);
|
|
}
|
|
|
|
onDialogueLine?.Invoke(this, dl);
|
|
}
|
|
}
|
|
|
|
public struct DialogueLine
|
|
{
|
|
public string text;
|
|
public float duration;
|
|
}
|
|
|
|
#region Editor
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
[CustomEditor(typeof(DialogueSystem))]
|
|
public class DialogueSystemEditor : Editor
|
|
{
|
|
private DialogueSystem _dialogue;
|
|
private string _key;
|
|
|
|
private void OnEnable()
|
|
{
|
|
_dialogue = target as DialogueSystem;
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
base.OnInspectorGUI();
|
|
|
|
_key = EditorGUILayout.TextField("key", _key);
|
|
|
|
if (GUILayout.Button("Play Line"))
|
|
{
|
|
_dialogue.PlayLine(_key);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#endregion |