using System; using System.Collections; using System.Collections.Generic; using AibisDream.Kit; using UnityEngine; using UnityEngine.Events; using Yarn.Unity; using DG.Tweening; namespace AibisDream { public class DialogController : Singleton { private const string BookManager = "BookManager"; private DialogueRunner dialogueRunner; private VariableStorageBehaviour _variableStorage; private readonly Dictionary> commandMap = new(); private readonly Dictionary> _pauseCommandMap = new(); # region controller状态标识 private bool _isTalking; public bool IsTalking { set { if (_isTalking == value) return; _isTalking = value; Debug.Log($"IsTalking 状态更改: {_isTalking}"); if (value) { OnDialogueStart?.Invoke(); } else { OnDialogueComplete?.Invoke(); } } get { return _isTalking; } } // 对话框被阻塞时不能继续对话框交互 public bool IsBlock { get; private set; } public bool quickRunMode; // 暂停对话 public bool isInPause; # endregion public static UnityAction OnDialogueStart; public static UnityAction OnDialogueComplete; private void Start() { dialogueRunner = GetComponentInChildren(); _variableStorage = GetComponentInChildren(); // 开关书交互 BookManager bookManager = GameObject.Find(BookManager).gameObject.GetComponent(); bookManager.OnBookClosed += () => { IsBlock = false; }; bookManager.OnBookOpen += () => { IsBlock = true; }; dialogueRunner.onDialogueStart.AddListener(() => { OnDialogueStart?.Invoke(); IsTalking = true; }); dialogueRunner.onDialogueComplete.AddListener(() => { OnDialogueComplete?.Invoke(); IsTalking = false; }); //dialogueRunner.AddCommandListener(_ => { IsTalking = false; }); // 对话结束时切下一个SO dialogueRunner.onDialogueComplete.AddListener(() => { // DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.Bubble); // StartCoroutine(GameLoopManager.Instance.NextSceneSo()); }); } #region 变量操作 public bool TryGetVariable(string variableName, out T result) { return _variableStorage.TryGetValue(variableName, out result); } public void SetVariable(string variableName, string value) { _variableStorage.SetValue(variableName, value); } public void SetVariable(string variableName, bool value) { _variableStorage.SetValue(variableName, value); } public void SetVariable(string variableName, float value) { _variableStorage.SetValue(variableName, value); } public bool Contains(string variableName) { return _variableStorage.Contains(variableName); } public void ClearVariables() { _variableStorage.Clear(); } #endregion /// /// 开启对话 /// /// Yarn组 public void StartDialog(YarnProject yarnProject) { dialogueRunner.VariableStorage.Clear(); dialogueRunner.SetProject(yarnProject); dialogueRunner.StartDialogue("Start"); } public void StartDialogNode(string nodeName) { if (CheckIfNodeExistInCurrentYarnProject(nodeName)) { dialogueRunner.StartDialogue(nodeName); } } public bool CheckIfNodeExistInCurrentYarnProject(string nodeName) { YarnProject currentProject = dialogueRunner.yarnProject; string[] nodeNames = currentProject.NodeNames; if (Array.Exists(nodeNames, item => item == nodeName)) { return true; } else { Debug.Log($"节点 {nodeName} 不存在!"); return false; } } #region 选项指令 /// /// 调用命令 /// /// 命令名 /// 选项 public void InvokeOptionCommand(string commandName, YarnOption[] options) { if (commandName == null) { Debug.Log("命令名为空"); return; } if (commandMap.TryGetValue(commandName, out var action)) { action(options); } else { Debug.LogWarning($"命令 {commandName} 不存在"); } } /// /// 注册命令 /// /// 命令名称 /// 注册名称 public void RegisterOptionCommand(string commandName, Action commandAction) { if (commandMap.ContainsKey(commandName)) { Debug.Log($"命令 {commandName} 已经存在,将被替换"); } commandMap[commandName] = commandAction; } /// /// 移除命令 /// /// 命令名称 public void RemoveOptionCommand(string commandName) { if (commandMap.ContainsKey(commandName)) { commandMap.Remove(commandName); } else { Debug.Log($"命令 {commandName} 不存在"); } } #endregion #region 暂停选项指令 /// /// 执行暂停命令 /// /// 命令名 /// 参数 public void InvokePauseCommand(string commandName, YarnContinueStep pauseCommand) { if (string.IsNullOrEmpty(commandName)) { Debug.Log("命令名为空"); return; } if (_pauseCommandMap.TryGetValue(commandName, out var action)) { action(pauseCommand); } else { Debug.LogWarning($"命令 {commandName} 不存在"); } } /// /// 注册暂停命令 /// /// 命令名 /// 注册命令函数 public void RegisterPauseCommand(string commandName, Action commandAction) { if (_pauseCommandMap.ContainsKey(commandName)) { Debug.Log($"命令 {commandName} 已经存在,将被替换"); } _pauseCommandMap[commandName] = commandAction; } /// /// 移除命令 /// /// 命令名称 public void RemovePauseCommand(string commandName) { if (_pauseCommandMap.ContainsKey(commandName)) { _pauseCommandMap.Remove(commandName); } else { Debug.Log($"命令 {commandName} 不存在"); } } #endregion #region 命令名 [YarnCommand("NextYarn")] public static void NextYarn() { DialogController.Instance.StartCoroutine(GameLoopManager.Instance.NextSceneSo()); } [YarnCommand("switch_tv")] public static void SwitchTV(string picName) { MainUIController.Instance.SwitchTV(picName); } [YarnCommand("indoor")] public static void Indoor(float duration = 1) { MainUIController.Instance.TVFadeOut(duration); } [YarnCommand("show_tv_scene")] public static void ShowTVScene(float duration) { MainUIController.Instance.TVFadeIn(duration); } [YarnCommand("load_scene")] public static IEnumerator LoadScene(string sceneName, float duration = 1) { HideDialog(); //yield return MainUIController.Instance.FadeInSync(duration); Camera.main.orthographicSize = 5; Camera.main.transform.position = new Vector3(0, 0, -10); yield return SceneLoader.Instance.LoadSceneAsync(sceneName); DialogCanvasManager.Instance.SwitchDialogView(sceneName == "ClinicScene" ? DialogViewType.Bubble : DialogViewType.OldBox); if (sceneName == "ClinicScene") { AudioManager.PlayAmb1Audio("amb_room"); } else { AudioManager.PlayAmb1Audio("amb_main"); } AudioManager.PlayAmb2Audio("amb_general"); } [YarnCommand("unload_scene")] public static IEnumerator UnloadScene(string sceneName) { yield return SceneLoader.Instance.UnloadSceneAsync(sceneName); } [YarnCommand("hide_dialog")] public static void HideDialog() { DialogCanvasManager.GetCurView().HideDialog(); } [YarnCommand("fade_in")] public static IEnumerator FadeIn(float duration) { return MainUIController.Instance.FadeInSync(duration); } [YarnCommand("fade_out")] public static IEnumerator FadeOut(float duration) { return MainUIController.Instance.FadeOutSync(duration); } [YarnCommand("show_obj")] public static IEnumerator ShowObj(string picName) { return MainUIController.Instance.ShowObj(picName); } [YarnCommand("hide_obj")] public static IEnumerator HideObj() { return MainUIController.Instance.HideObj(); } [YarnCommand("move_to_fix")] public static IEnumerator MoveToFix() { bool isCompleted = false; Sequence s = DOTween.Sequence(); s.Append(Camera.main.transform.DOMove(new UnityEngine.Vector3(6.8f, 0, -10), 2f)) .OnComplete(() => { // 动画完成后的反馈操作 Debug.Log("Move_to_fix sequence completed."); isCompleted = true; }); // 等待动画完成 yield return new WaitUntil(() => isCompleted); // 动画完成后的其他操作 Debug.Log("Continuing after Move_to_fix sequence."); } [YarnCommand("move_out_fix")] public static void MoveOutFix() { Camera.main.transform.position = new UnityEngine.Vector3(6.8f, 0, -10); Sequence s = DOTween.Sequence(); //s.AppendInterval(0.5f); s.Append(Camera.main.transform.DOMove(new UnityEngine.Vector3(0, 0, -10), 2f)); } [YarnCommand("switch_dialog_view")] public static void SwitchDialogView(string viewName) { DialogCanvasManager.Instance.SwitchDialogView(Enum.Parse(viewName)); } #endregion } }