using System.Collections; using System.Collections.Generic; using AibisDream.Framework; using UnityEngine; using UnityEngine.UI; namespace AibisDream { public class CursorManager : MonoBehaviour { private const float DelayTime = 0.2f; [Header("指针图片")] public Sprite defaultCursor; public Sprite nextTalk, talking, option, interactive, holding, disable, eye; private Image _cursor; private RectTransform _cursorCanvas; #region 状态相关 private Coroutine _switchCoroutine; private CursorState _curState = CursorState.Default; #endregion // 卸载时注销事件 private List _unRegisters = new(); public void Awake() { InitRefs(); InitCursor(); } private void InitCursor() { Cursor.visible = false; SwitchCursor(defaultCursor); } private void OnEnable() { RegisterEvent(); } private void OnDisable() { // 注销所有事件 foreach (var eventUnRegister in _unRegisters) { eventUnRegister.UnRegister(); } _unRegisters.Clear(); } private void InitRefs() { _cursor = transform.Find("Cursor").GetComponent(); _cursorCanvas = GetComponent(); } private void RegisterEvent() { // 此处监听所有可能对鼠标状态产生影响的事件 // 对话相关 _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineStart, _ => SwitchCursor(talking))); _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineShowed, () => SwitchCursor(nextTalk))); _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineEnd, () => SwitchCursorDelay(defaultCursor))); _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.OptionShow, () => SwitchCursor(option))); _unRegisters.Add( EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, _ => SwitchCursorDelay(defaultCursor))); // 交互相关 _unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.Start, OnInteractiveStart)); _unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.End, OnInteractiveEnd)); } private void LateUpdate() { // 将虚拟指针与鼠标位置同步 RectTransformUtility.ScreenPointToLocalPointInRectangle(_cursorCanvas, Input.mousePosition, CameraKit.Instance.uiCamera, out var worldPos); _cursor.rectTransform.localPosition = worldPos; // 在输入状态,要单独处理 } #region 交互状态相关 private void OnInteractiveStart() { _curState = CursorState.Interactive; } private void OnInteractiveEnd() { _curState = CursorState.Interactive; } #endregion #region 指针切换 /// /// 直接切指针 /// /// 指针图片 private void SwitchCursor(Sprite sprite) { StopDelayCursor(); _cursor.sprite = sprite; } /// /// 延迟切换指针。如果后面有其他切换状态,就直接打断 /// /// 指针图片 private void SwitchCursorDelay(Sprite sprite) { StopDelayCursor(); _switchCoroutine = StartCoroutine(SwitchCursorAsync(sprite)); } private IEnumerator SwitchCursorAsync(Sprite sprite) { yield return new WaitForSeconds(DelayTime); _cursor.sprite = sprite; } private void StopDelayCursor() { if (_switchCoroutine != null) { StopCoroutine(_switchCoroutine); _switchCoroutine = null; } } #endregion } public enum CursorState { Default, Interactive, Eye } }