using System; using System.Collections.Generic; 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 onDialogueLine; private readonly Dictionary _fmodKeyCache = new Dictionary(); private void OnEnable() { // cache all dialogue keys for FMOD at start to avoid allocations later foreach (var key in DialogueDatabase.Keys) { _fmodKeyCache[key] = $"{_settings.FMODPrefix}{key}"; } } public void PlayLine(string key) { // retrieve cached key var fmodKey = _fmodKeyCache[key]; var eventDescription = FMODUnity.RuntimeManager.GetEventDescription(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.isValid()) { // assign values and play audio // get dialogue line duration from FMOD eventDescription.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); } else { // no event available boooooooo Debug.LogError($"FMOD event desc for key {fmodKey} is not valid", this); } 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