Files
aibis-dream/Assets/Scripts/Dialog System/DialogController.cs
T
2024-12-05 04:06:50 +00:00

396 lines
12 KiB
C#

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<DialogController>
{
private const string BookManager = "BookManager";
private DialogueRunner dialogueRunner;
private VariableStorageBehaviour _variableStorage;
private readonly Dictionary<string, Action<YarnOption[]>> commandMap = new();
private readonly Dictionary<string, Action<YarnContinueStep>> _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<DialogueRunner>();
_variableStorage = GetComponentInChildren<InMemoryVariableStorage>();
// 开关书交互
BookManager bookManager = GameObject.Find(BookManager).gameObject.GetComponent<BookManager>();
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<T>(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
/// <summary>
/// 开启对话
/// </summary>
/// <param name="yarnProject">Yarn组</param>
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 选项指令
/// <summary>
/// 调用命令
/// </summary>
/// <param name="commandName">命令名</param>
/// <param name="options">选项</param>
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} 不存在");
}
}
/// <summary>
/// 注册命令
/// </summary>
/// <param name="commandName">命令名称</param>
/// <param name="commandAction">注册名称</param>
public void RegisterOptionCommand(string commandName, Action<YarnOption[]> commandAction)
{
if (commandMap.ContainsKey(commandName))
{
Debug.Log($"命令 {commandName} 已经存在,将被替换");
}
commandMap[commandName] = commandAction;
}
/// <summary>
/// 移除命令
/// </summary>
/// <param name="commandName">命令名称</param>
public void RemoveOptionCommand(string commandName)
{
if (commandMap.ContainsKey(commandName))
{
commandMap.Remove(commandName);
}
else
{
Debug.Log($"命令 {commandName} 不存在");
}
}
#endregion
#region 暂停选项指令
/// <summary>
/// 执行暂停命令
/// </summary>
/// <param name="commandName">命令名</param>
/// <param name="pauseCommand">参数</param>
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} 不存在");
}
}
/// <summary>
/// 注册暂停命令
/// </summary>
/// <param name="commandName">命令名</param>
/// <param name="commandAction">注册命令函数</param>
public void RegisterPauseCommand(string commandName, Action<YarnContinueStep> commandAction)
{
if (_pauseCommandMap.ContainsKey(commandName))
{
Debug.Log($"命令 {commandName} 已经存在,将被替换");
}
_pauseCommandMap[commandName] = commandAction;
}
/// <summary>
/// 移除命令
/// </summary>
/// <param name="commandName">命令名称</param>
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<DialogViewType>(viewName));
}
#endregion
}
}