diff --git a/Assets/Scripts/FixSystemNew/Open/ShockSystem.cs b/Assets/Scripts/FixSystemNew/Open/ShockSystem.cs
index 0f6de8d8b..d425c27bd 100644
--- a/Assets/Scripts/FixSystemNew/Open/ShockSystem.cs
+++ b/Assets/Scripts/FixSystemNew/Open/ShockSystem.cs
@@ -1,16 +1,20 @@
-using UnityEngine;
-using UnityEngine.UI;
-using DG.Tweening;
-using TMPro;
-using RainbowArt.CleanFlatUI;
+using System.Collections;
using System.Collections.Generic;
-using AibisDream.Framework;
-using UnityEngine.EventSystems;
+using System.Linq;
+using AibisDream;
using AibisDream.FixSystem;
-using System.Collections;
-using AibisDream; // 添加 SpriteFlashSystem 的命名空间
+using AibisDream.Framework;
+using DG.Tweening;
+using RainbowArt.CleanFlatUI;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
-public class ShockSystem : MonoBehaviour
+///
+/// 电击器系统。拉杆交互通过 EventTriggerEx 统一管理,支持 EventSystemEx.isLocked 与 IInteraction,
+/// 光标由 EventTriggerEx → EventSystemEx → CursorManager 自动驱动。
+///
+public class ShockSystem : MonoBehaviour, IInteraction
{
[Header("References")]
[SerializeField] private Transform shockDevice; // 电击器
@@ -98,18 +102,74 @@ public class ShockSystem : MonoBehaviour
private Tweener abnormalLeverShakeTweener; // 异常状态下拉杆震动动画
private Tweener abnormalPanelShakeTweener; // 异常状态下面板震动动画
private Color normalProgressBarColor; // 正常状态下进度条颜色
+ private EventTriggerEx _eventTrigger;
+ private ShockLeverInteractionBridge _leverBridge;
+ private bool _useEventTrigger;
+ private bool _leverInputLocked;
+ private bool _leverPointerOver;
// 公共访问器
public float FlashDuration => flashDuration;
public float FlashInterval => flashInterval;
public int FlashCount => flashCount;
+ #region IInteraction
+
+ public bool IsActive => true;
+ public bool IsAvailable => !isAbnormalState && !_leverInputLocked;
+ public GameObject GetGameObject() => gameObject;
+
+ #endregion
+
private void Awake()
+ {
+ FixSystemCenter.SystemDic.Register(this);
+ EnsureLeverInteraction();
+ }
+
+ ///
+ /// 为拉杆挂接 ShockLeverInteractionBridge + EventTriggerEx(对齐 CrankController)。
+ /// 悬停光标另用 LateUpdate 射线校正:指针 Collider 细长且会旋转,EventSystem 易丢 PointerExit。
+ ///
+ private void EnsureLeverInteraction()
+ {
+ if (lever == null) return;
+
+ var leverGo = lever.gameObject;
+ if (leverGo.GetComponent() == null)
{
- // 注册
- FixSystemCenter.SystemDic.Register(this);
+#if UNITY_EDITOR
+ Debug.LogWarning("[ShockSystem] 拉杆未找到 Collider2D!请添加 Collider2D 以接入交互与光标。", this);
+#endif
+ return;
}
+ _leverBridge = leverGo.GetComponent();
+ if (_leverBridge == null)
+ _leverBridge = leverGo.AddComponent();
+
+ _eventTrigger = leverGo.GetComponent();
+ if (_eventTrigger == null)
+ _eventTrigger = leverGo.AddComponent();
+
+ _useEventTrigger = true;
+ EnsureEventTriggerEntries();
+ _eventTrigger.Register(EventTriggerType.PointerDown, OnEventPointerDown);
+ _eventTrigger.Register(EventTriggerType.PointerUp, OnEventPointerUp);
+ _eventTrigger.Register(EventTriggerType.Drag, OnEventDrag);
+ }
+
+ private void EnsureEventTriggerEntries()
+ {
+ if (_eventTrigger == null) return;
+ var triggers = _eventTrigger.triggers;
+ var needed = new[] { EventTriggerType.PointerDown, EventTriggerType.PointerUp, EventTriggerType.Drag };
+ foreach (var t in needed)
+ {
+ if (triggers.Any(e => e.eventID == t)) continue;
+ triggers.Add(new EventTrigger.Entry { eventID = t });
+ }
+ }
private void Start()
{
@@ -152,77 +212,183 @@ public class ShockSystem : MonoBehaviour
}
else
{
- HandleLeverInput();
+ if (_useEventTrigger)
+ UpdateLeverReturn();
+ else
+ HandleLeverInputFallback();
+
UpdateLeverRotation();
UpdateCharging();
}
}
- private void HandleLeverInput()
+ private void LateUpdate()
{
+ SyncLeverHoverCursor();
+ }
+
+ #region 拉杆输入(EventTriggerEx 驱动 / 回退)
+
+ private bool IsMouseOverLever()
+ {
+ if (lever == null) return false;
+ var cam = Camera.main;
+ if (cam == null) return false;
+
+ Ray ray = cam.ScreenPointToRay(Input.mousePosition);
+ RaycastHit2D hit = Physics2D.GetRayIntersection(ray, float.MaxValue);
+ if (hit.collider != null && hit.collider.transform == lever)
+ return true;
+
+ hit = Physics2D.Raycast(ray.origin, ray.direction);
+ return hit.collider != null && hit.collider.transform == lever;
+ }
+
+ ///
+ /// 以射线结果校正悬停光标,弥补细长旋转 Collider 丢失 PointerExit 的情况。
+ ///
+ private void SyncLeverHoverCursor()
+ {
+ if (_leverBridge == null || EventSystemEx.Instance == null) return;
+
+ bool over = IsAvailable && IsMouseOverLever();
+ if (over == _leverPointerOver) return;
+
+ _leverPointerOver = over;
+ if (over)
+ EventSystemEx.Instance.OnPointerEnter(_leverBridge);
+ else
+ EventSystemEx.Instance.OnPointerExit(_leverBridge);
+ }
+
+ private void OnEventPointerDown(BaseEventData eventData)
+ {
+ if (!IsAvailable || (EventSystemEx.Instance != null && EventSystemEx.Instance.isLocked)) return;
+ if (eventData is not PointerEventData { button: PointerEventData.InputButton.Left } pointerData) return;
+
+ isDraggingLever = true;
+ lastMousePosition = pointerData.position;
+ }
+
+ private void OnEventPointerUp(BaseEventData eventData)
+ {
+ if (eventData is not PointerEventData { button: PointerEventData.InputButton.Left }) return;
+ EndLeverDrag();
+ }
+
+ private void OnEventDrag(BaseEventData eventData)
+ {
+ if (!isDraggingLever || !IsAvailable || (EventSystemEx.Instance != null && EventSystemEx.Instance.isLocked)) return;
+ if (eventData is not PointerEventData pointerData) return;
+
+ ApplyLeverDrag(pointerData.position);
+ }
+
+ /// 无 EventTriggerEx 时回退到 Input + Raycast。
+ private void HandleLeverInputFallback()
+ {
+ if (!IsAvailable || (EventSystemEx.Instance != null && EventSystemEx.Instance.isLocked))
+ {
+ UpdateLeverReturn();
+ return;
+ }
+
if (Input.GetMouseButtonDown(0))
{
- // 检查是否点击到杆
- Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
- RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);
-
- if (hit.collider != null && hit.collider.transform == lever)
+ var cam = Camera.main;
+ if (cam != null && lever != null)
{
- isDraggingLever = true;
- lastMousePosition = Input.mousePosition;
+ Ray ray = cam.ScreenPointToRay(Input.mousePosition);
+ RaycastHit2D hit = Physics2D.GetRayIntersection(ray, float.MaxValue);
+ if (hit.collider != null && hit.collider.transform == lever)
+ {
+ isDraggingLever = true;
+ lastMousePosition = Input.mousePosition;
+ }
}
}
else if (Input.GetMouseButtonUp(0))
{
- isDraggingLever = false;
- // 停止充能
- if (isCharging)
- {
- isCharging = false;
- if (currentProgress >= progressBar.MaxValue)
- {
- DialogController.Instance.StartDialogNode(shockEffectNode);
- }
- ResetProgress();
- }
+ EndLeverDrag();
}
if (isDraggingLever)
- {
- Vector3 mouseDelta = Input.mousePosition - lastMousePosition;
- float angleDelta = mouseDelta.x * 0.5f; // 调整灵敏度
-
- targetLeverAngle = Mathf.Clamp(targetLeverAngle + angleDelta, 0f, maxLeverAngle);
- lastMousePosition = Input.mousePosition;
-
- // 根据杆的角度计算进度
- float progressRatio = targetLeverAngle / maxLeverAngle;
- if (progressRatio > 0 && !isCharging)
- {
- isCharging = true;
- StartCharging();
- // 开始播放充能音效
- AibisDream.Kit.AudioManager.Instance.PlaySfx(chargingEvent, chargingAudioKey);
- }
- }
+ ApplyLeverDrag(Input.mousePosition);
else
+ UpdateLeverReturn();
+ }
+
+ private void ApplyLeverDrag(Vector3 mousePosition)
+ {
+ Vector3 mouseDelta = mousePosition - lastMousePosition;
+ float angleDelta = mouseDelta.x * 0.5f;
+ targetLeverAngle = Mathf.Clamp(targetLeverAngle + angleDelta, 0f, maxLeverAngle);
+ lastMousePosition = mousePosition;
+
+ float progressRatio = targetLeverAngle / maxLeverAngle;
+ if (progressRatio > 0 && !isCharging)
{
- // 杆自动回弹
- targetLeverAngle = Mathf.MoveTowards(targetLeverAngle, 0f, leverReturnSpeed * Time.deltaTime);
-
- // 如果杆已经回弹到接近0度,确保停止充能
- if (targetLeverAngle < 0.1f && isCharging)
- {
- isCharging = false;
- if (currentProgress >= progressBar.MaxValue)
- {
- DialogController.Instance.StartDialogNode(shockEffectNode);
- }
- ResetProgress();
- }
+ isCharging = true;
+ StartCharging();
+ AibisDream.Kit.AudioManager.Instance.PlaySfx(chargingEvent, chargingAudioKey);
}
}
+ private void UpdateLeverReturn()
+ {
+ if (isDraggingLever) return;
+
+ targetLeverAngle = Mathf.MoveTowards(targetLeverAngle, 0f, leverReturnSpeed * Time.deltaTime);
+
+ if (targetLeverAngle < 0.1f && isCharging)
+ {
+ isCharging = false;
+ if (currentProgress >= progressBar.MaxValue)
+ DialogController.Instance.StartDialogNode(shockEffectNode);
+ ResetProgress();
+ }
+ }
+
+ private void EndLeverDrag()
+ {
+ if (!isDraggingLever && !isCharging)
+ {
+ isDraggingLever = false;
+ return;
+ }
+
+ isDraggingLever = false;
+ if (!isCharging) return;
+
+ isCharging = false;
+ bool shouldShock = currentProgress >= progressBar.MaxValue;
+ ResetProgress();
+
+ // 先清交互光标状态,再开对话(DialogStart 会 isLocked,旧逻辑会跳过 Up/EndDrag 清理)
+ if (_leverBridge != null && EventSystemEx.Instance != null)
+ EventSystemEx.Instance.UnRegister(_leverBridge);
+ _leverPointerOver = false;
+
+ if (shouldShock)
+ DialogController.Instance.StartDialogNode(shockEffectNode);
+ }
+
+ private void ForceClearLeverInteraction()
+ {
+ isDraggingLever = false;
+ if (isCharging)
+ {
+ isCharging = false;
+ ResetProgress();
+ }
+
+ if (_leverBridge != null && EventSystemEx.Instance != null)
+ EventSystemEx.Instance.UnRegister(_leverBridge);
+ _leverPointerOver = false;
+ }
+
+ #endregion
+
private void UpdateLeverRotation()
{
if (lever != null)
@@ -486,12 +652,11 @@ public class ShockSystem : MonoBehaviour
if (isAbnormal)
{
- // 启动异常状态效果
+ ForceClearLeverInteraction();
StartAbnormalEffects();
}
else
{
- // 停止异常状态效果
StopAbnormalEffects();
}
}
@@ -589,15 +754,10 @@ public class ShockSystem : MonoBehaviour
// 自动充能并释放
public IEnumerator AutoChargeAndRelease(float duration = 1f)
{
- // 保存当前异常状态
bool originalAbnormalState = isAbnormalState;
-
- // 临时禁用异常状态
isAbnormalState = false;
-
- // 禁用玩家输入
- bool originalIsDraggingLever = isDraggingLever;
- isDraggingLever = false;
+ _leverInputLocked = true;
+ ForceClearLeverInteraction();
// 设置杆的角度
targetLeverAngle = maxLeverAngle;
@@ -625,7 +785,7 @@ public class ShockSystem : MonoBehaviour
// 恢复原始设置
progressIncreaseSpeed = originalProgressIncreaseSpeed;
isCharging = false;
- isDraggingLever = originalIsDraggingLever;
+ _leverInputLocked = false;
// 重置杆的角度
targetLeverAngle = 0f;
@@ -643,6 +803,15 @@ public class ShockSystem : MonoBehaviour
private void OnDestroy()
{
+ if (_eventTrigger != null)
+ {
+ _eventTrigger.UnRegister(EventTriggerType.PointerDown, OnEventPointerDown);
+ _eventTrigger.UnRegister(EventTriggerType.PointerUp, OnEventPointerUp);
+ _eventTrigger.UnRegister(EventTriggerType.Drag, OnEventDrag);
+ }
+
+ ForceClearLeverInteraction();
+
if (progressTweener != null)
{
progressTweener.Kill();
@@ -698,4 +867,21 @@ public class ShockSystem : MonoBehaviour
}
}
}
+}
+
+///
+/// 电击器拉杆交互桥接:挂在 Collider 所在子物体上,将 IInteraction 转交给父级 ShockSystem(对齐 CrankInteractionBridge)。
+///
+public class ShockLeverInteractionBridge : MonoBehaviour, IInteraction
+{
+ private ShockSystem _shockSystem;
+
+ private void Awake()
+ {
+ _shockSystem = GetComponentInParent();
+ }
+
+ public bool IsActive => _shockSystem?.IsActive ?? true;
+ public bool IsAvailable => _shockSystem?.IsAvailable ?? true;
+ public GameObject GetGameObject() => gameObject;
}
\ No newline at end of file