using System.Linq; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; namespace AibisDream.Framework { /// /// EventTrigger扩展 /// [RequireComponent(typeof(Collider2D))] public class EventTriggerEx : EventTrigger { private IInteraction _interaction; private IInteraction Interaction { get { // 惰性获取:bridge 可能在 EventTriggerEx 之后才 AddComponent if (_interaction == null) _interaction = GetComponent(); return _interaction; } } private void Awake() { _interaction = GetComponent(); } /// /// 注册事件 /// /// 事件类型 /// 函数 public void Register(EventTriggerType triggerType, UnityAction action) { if (TryGetTriggerEvent(triggerType, out var triggerEvent)) { triggerEvent.AddListener(action); } else { Debug.LogWarning($"{triggerType.ToString()}未添加"); } } /// /// 卸载事件 /// /// 事件类型 /// 函数 public void UnRegister(EventTriggerType triggerType, UnityAction action) { if (TryGetTriggerEvent(triggerType, out var triggerEvent)) { triggerEvent.RemoveListener(action); } else { Debug.LogWarning($"{triggerType.ToString()}未添加"); } } /// /// 获取触发事件 /// /// 事件类型 /// 事件 /// 是否存在 private bool TryGetTriggerEvent(EventTriggerType triggerType, out TriggerEvent triggerEvent) { var entry = triggers.FirstOrDefault(item => item.eventID == triggerType); if (entry == null) { triggerEvent = null; return false; } else { triggerEvent = entry.callback; return true; } } private bool CanStartInteraction() { return Interaction != null && Interaction.IsAvailable && EventSystemEx.Instance != null && !EventSystemEx.Instance.isLocked; } public override void OnPointerEnter(PointerEventData data) { if (Interaction != null && EventSystemEx.Instance != null) EventSystemEx.Instance.OnPointerEnter(Interaction); base.OnPointerEnter(data); } public override void OnPointerExit(PointerEventData data) { // 退出必须始终清理,否则旋转/细长 Collider 丢 Exit 时会卡住光标 if (Interaction != null && EventSystemEx.Instance != null) EventSystemEx.Instance.OnPointerExit(Interaction); base.OnPointerExit(data); } public override void OnPointerDown(PointerEventData eventData) { // 对话等场景 isLocked 时仍要让 EventTrigger 上注册的回调执行(如塔罗 PointerDown), // 否则会出现能 Hover、但 Down/Up/Click 全不进组件的问题。 // 仅「开始」交互时受 isLocked / IsAvailable 门控;清理路径见 Up/EndDrag。 if (CanStartInteraction()) EventSystemEx.Instance.OnPointerDown(Interaction); base.OnPointerDown(eventData); } public override void OnPointerUp(PointerEventData eventData) { // 松手必须始终清理 holding,否则充能结束开对话把 isLocked 置真后会永远卡在抓取光标 if (Interaction != null && EventSystemEx.Instance != null) EventSystemEx.Instance.OnPointerUp(Interaction); base.OnPointerUp(eventData); } public override void OnDrag(PointerEventData eventData) { if (CanStartInteraction()) { EventSystemEx.Instance.OnDrag(Interaction); base.OnDrag(eventData); } } public override void OnEndDrag(PointerEventData eventData) { // 与 PointerUp 相同:清理不受 isLocked 门控 if (Interaction != null && EventSystemEx.Instance != null) EventSystemEx.Instance.OnEndDrag(Interaction); base.OnEndDrag(eventData); } public override void OnBeginDrag(PointerEventData eventData) { if (CanStartInteraction()) { EventSystemEx.Instance.OnBeginDrag(Interaction); base.OnBeginDrag(eventData); } } public override void OnPointerClick(PointerEventData eventData) { if (CanStartInteraction()) { // EventSystemEx.Instance.OnPointerClick(Interaction); } base.OnPointerClick(eventData); } void OnDestroy() { if (EventSystemEx.Instance != null && Interaction != null) EventSystemEx.Instance.UnRegister(Interaction); } } public interface IInteraction { // 判断是否激活,激活就正常显示鼠标,否则就显示禁用标志 public bool IsActive { get; } // 判断是否可用,可用就正常显示鼠标,否则就保持原有标志不变 public bool IsAvailable { get; } // 返回GameObject public GameObject GetGameObject(); } }