using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AibisDream;
using AibisDream.FixSystem;
using AibisDream.Framework;
using DG.Tweening;
using RainbowArt.CleanFlatUI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
///
/// 电击器系统。拉杆交互通过 EventTriggerEx 统一管理,支持 EventSystemEx.isLocked 与 IInteraction,
/// 光标由 EventTriggerEx → EventSystemEx → CursorManager 自动驱动。
///
public class ShockSystem : MonoBehaviour, IInteraction
{
[Header("References")]
[SerializeField] private Transform shockDevice; // 电击器
[SerializeField] private Transform leftShockDevice; // 左电击装置
[SerializeField] private Transform rightShockDevice; // 右电击装置
[SerializeField] private Transform operationPanel; // 操作面板
[SerializeField] private ProgressBarGridLinear progressBar; // 进度条
[SerializeField] private Transform lever; // 转动杆
[SerializeField] private SpriteRenderer flashHeadSpriteRenderer; // 头部闪烁精灵渲染器
[SerializeField] private SpriteRenderer flashBackgroundSpriteRenderer; // 背景闪烁精灵渲染器
[SerializeField] private SpriteRenderer flashSpriteRenderer;
[SerializeField] private List flashHeadSprites; // 头部闪烁精灵列表
[SerializeField] private SpriteFlashSystem spriteFlashSystem; // Sprite闪烁系统
[SerializeField] private GameObject sparkEffect1; // 火花特效1
[SerializeField] private GameObject sparkEffect2; // 火花特效2
[SerializeField] private Image progressBarFg; // 进度条前景
[Header("Settings")]
[SerializeField] private bool isSystemOn = false; // 系统开关状态
[SerializeField] private Vector3 leftShockDeviceTargetPos; // 左电击装置目标位置
[SerializeField] private Vector3 rightShockDeviceTargetPos; // 右电击装置目标位置
[SerializeField] private Vector3 leftShockDeviceStartPos; // 左电击装置起始位置
[SerializeField] private Vector3 rightShockDeviceStartPos; // 右电击装置起始位置
[SerializeField] private Vector3 operationPanelTargetPos; // 操作面板目标位置
[SerializeField] private Vector3 operationPanelStartPos; // 操作面板起始位置
[SerializeField] private float moveDuration = 1f; // 移动动画时长
[SerializeField] private float shockDelay = 0.5f; // 释放电击延迟
[SerializeField] private float progressIncreaseSpeed = 1f; // 进度增加基础速度
[SerializeField] private float maxSliderValue = 3f; // 滑块最大值
[SerializeField] private float progressDecreaseDuration = 1f; // 进度下降持续时间
[SerializeField] private string shockEffectNode = "ShockEffect"; // 电击效果节点名称
[Header("Shock Effects")]
[SerializeField] private float flashDuration = 0.1f; // 每次闪烁持续时间
[SerializeField] private float flashInterval = 0.1f; // 闪烁间隔
[SerializeField] private int flashCount = 3; // 闪烁次数
[SerializeField] private float strength = 1f; // 震动强度
[SerializeField] private int vibrate = 10; // 震动次数
[SerializeField] private float minVibrateStrength = 0.05f; // 最小震动强度
[SerializeField] private float maxVibrateStrength = 0.2f; // 最大震动强度
[SerializeField] private float vibrateInterval = 0.1f; // 震动间隔
[SerializeField] private float deviceShakeAmount = 0.1f; // 电击器震动幅度
[SerializeField] private float deviceShakeSpeed = 10f; // 电击器震动速度
[Header("Auto Charge Settings")]
[SerializeField] private float autoChargeSpeed = 5f; // 自动充能速度
[SerializeField] private float autoChargeDuration = 1f; // 自动充能持续时间
[Header("Lever Settings")]
[SerializeField] private float maxLeverAngle = 90f; // 最大转动角度
[SerializeField] private float leverReturnSpeed = 300f; // 杆回弹速度
[SerializeField] private float leverSmoothTime = 0.1f; // 杆转动平滑时间
[Header("Abnormal State Settings")]
[SerializeField] private bool isAbnormalState = false; // 是否处于异常状态
[SerializeField] private float abnormalLeverShakeAmount = 30f; // 异常状态下拉杆震动幅度
[SerializeField] private float abnormalLeverShakeSpeed = 20f; // 异常状态下拉杆震动速度
[SerializeField] private float abnormalPanelShakeAmount = 0.1f; // 异常状态下面板震动幅度
[SerializeField] private float abnormalPanelShakeSpeed = 15f; // 异常状态下面板震动速度
[SerializeField] private Color abnormalProgressBarColor = Color.red; // 异常状态下进度条颜色
[Header("Audio Settings")]
[SerializeField] private string chargingEvent = "event:/FollowInput/defib/defib_charging";
[SerializeField] private string shockEvent = "event:/FollowInput/defib/defib_shock";
[SerializeField] private string defibProgressParam = "defibProgress";
[SerializeField] private string shockReverbParam = "reverb";
[SerializeField] private float shockFlashDelay = 0.05f; // 声音与闪烁的延迟,可配置
[Range(0,1)] public float shockReverb = 0f; // 0=真实,1=梦境
private string chargingAudioKey = "defib_charging";
private string shockAudioKey = "defib_shock";
private bool isCharging = false;
private float currentProgress = 0f;
private float currentLeverAngle = 0f; // 当前杆的角度
private float targetLeverAngle = 0f; // 目标杆的角度
private float leverVelocity = 0f; // 用于平滑转动
private bool isDraggingLever = false; // 是否正在拖动杆
private Vector3 lastMousePosition; // 上一帧鼠标位置
private Tweener progressTweener; // 用于存储进度条动画
private Sequence flashSequence; // 用于存储闪烁动画序列
private int currentFlashHeadIndex = 0; // 当前闪烁头部精灵索引
private float lastVibrateTime = 0f; // 上次震动时间
private Vector3 leftDeviceOriginalPos; // 左电击装置原始位置
private Vector3 rightDeviceOriginalPos; // 右电击装置原始位置
private Tweener deviceShakeTweener; // 电击器震动动画
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)
{
#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()
{
// 保存电击器原始位置
if (leftShockDevice != null)
{
leftDeviceOriginalPos = leftShockDevice.localPosition;
}
if (rightShockDevice != null)
{
rightDeviceOriginalPos = rightShockDevice.localPosition;
}
if (operationPanel != null)
{
operationPanelStartPos = operationPanel.localPosition;
}
// 初始化杆的位置
if (lever != null)
{
lever.localRotation = Quaternion.Euler(0, 0, 0);
}
// 保存正常状态下的进度条颜色
if (progressBarFg != null)
{
normalProgressBarColor = progressBarFg.color;
}
// 确保火花效果初始状态为关闭
if (sparkEffect1 != null) sparkEffect1.SetActive(false);
if (sparkEffect2 != null) sparkEffect2.SetActive(false);
}
private void Update()
{
if (isAbnormalState)
{
UpdateAbnormalState();
}
else
{
if (_useEventTrigger)
UpdateLeverReturn();
else
HandleLeverInputFallback();
UpdateLeverRotation();
UpdateCharging();
}
}
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))
{
var cam = Camera.main;
if (cam != null && lever != null)
{
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))
{
EndLeverDrag();
}
if (isDraggingLever)
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 <= 0f)
{
if (isCharging)
{
isCharging = false;
ResetProgress();
}
return;
}
if (progressRatio > 0 && !isCharging)
{
progressTweener?.Kill();
progressTweener = null;
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)
{
currentLeverAngle = Mathf.SmoothDamp(currentLeverAngle, targetLeverAngle, ref leverVelocity, leverSmoothTime);
lever.localRotation = Quaternion.Euler(0, 0, -currentLeverAngle);
}
}
// public void InitializeShock()
// {
// // 移动电击器和操作面板到指定位置
// shockDevice.DOLocalMove(shockDeviceTargetPos, moveDuration);
// operationPanel.DOLocalMove(operationPanelTargetPos, moveDuration);
// powerSlider.EnableSliderInteraction();
// }
// public void SetFlashBack(bool useFlashback,)
// {
// this.useFlashback = useFlashback;
// }
public IEnumerator StartShock()
{
// 移动左右电击装置到各自的目标位置
var moveLeft = leftShockDevice.DOLocalMove(leftShockDeviceTargetPos, moveDuration);
var moveRight = rightShockDevice.DOLocalMove(rightShockDeviceTargetPos, moveDuration);
var movePanel = operationPanel.DOLocalMove(operationPanelTargetPos, moveDuration);
yield return moveLeft.WaitForCompletion();
yield return moveRight.WaitForCompletion();
yield return movePanel.WaitForCompletion();
}
public IEnumerator StopShock()
{
var moveLeft = leftShockDevice.DOLocalMove(leftDeviceOriginalPos, moveDuration);
var moveRight = rightShockDevice.DOLocalMove(rightDeviceOriginalPos, moveDuration);
var movePanel = operationPanel.DOLocalMove(operationPanelStartPos, moveDuration);
yield return moveLeft.WaitForCompletion();
yield return moveRight.WaitForCompletion();
yield return movePanel.WaitForCompletion();
}
private void ResetProgress()
{
// 停止充能音效
AibisDream.Kit.AudioManager.Instance.StopSfx(chargingAudioKey);
// 开始进度条平滑下降
if (progressTweener != null)
{
progressTweener.Kill();
}
float startProgress = currentProgress;
progressTweener = DOTween.To(
() => currentProgress,
x =>
{
currentProgress = x;
progressBar.CurrentValue = Mathf.FloorToInt(x);
},
0f,
progressDecreaseDuration
).SetEase(Ease.OutQuad);
}
private void UpdateCharging()
{
if (!isCharging) return;
// 根据杆的角度计算进度增加速度
float progressRatio = currentLeverAngle / maxLeverAngle;
float speedMultiplier = 1f + progressRatio;
currentProgress += progressIncreaseSpeed * speedMultiplier * Time.deltaTime;
// 更新进度条
int progressValue = Mathf.FloorToInt(currentProgress);
progressBar.CurrentValue = progressValue;
// 同步defibProgress参数到音频
float progressParam = Mathf.Clamp01(currentProgress / progressBar.MaxValue);
AibisDream.Kit.AudioManager.Instance.SetSfxParam(chargingAudioKey, defibProgressParam, progressParam);
// 计算震动强度
float currentVibrateStrength = Mathf.Lerp(minVibrateStrength, maxVibrateStrength, progressRatio);
// 检查是否需要震动
if (Time.time - lastVibrateTime >= vibrateInterval)
{
// 电击器震动
if (shockDevice != null)
{
if (deviceShakeTweener != null)
{
deviceShakeTweener.Kill();
}
// 计算电击器震动幅度(随进度增加)
float currentShakeAmount = deviceShakeAmount * progressRatio;
// 创建电击器震动动画
deviceShakeTweener = shockDevice.DOShakePosition(
vibrateInterval,
currentShakeAmount,
vibrate,
deviceShakeSpeed,
false,
false
).SetEase(Ease.Linear);
}
lastVibrateTime = Time.time;
}
// 检查是否达到最大值
if (currentProgress >= progressBar.MaxValue)
{
// 保持最大值
currentProgress = progressBar.MaxValue;
progressBar.CurrentValue = Mathf.FloorToInt(currentProgress);
// 触发释放效果
DialogController.Instance.StartDialogNode(shockEffectNode);
// 停止充能
isCharging = false;
// 强制杆回弹
targetLeverAngle = 0f;
// 重置进度
ResetProgress();
}
}
private void StartCharging()
{
if (!isCharging) return;
// 重置上次震动时间
lastVibrateTime = Time.time;
}
public IEnumerator PlayFlashEffect()
{
if (flashSequence != null)
{
flashSequence.Kill();
}
// 先播放shock音效
AibisDream.Kit.AudioManager.Instance.PlaySfx(shockEvent, shockAudioKey);
// 设置reverb参数
AibisDream.Kit.AudioManager.Instance.SetSfxParam(shockAudioKey, shockReverbParam, shockReverb);
// 延迟shockFlashDelay秒后再闪烁
yield return new WaitForSeconds(shockFlashDelay);
// 获取ECG波形组件
var cablePanel = FixPanelSystem.GetRepairPanel();
var originalWaveType = cablePanel?.GetCurrentWaveType();
flashSequence = DOTween.Sequence();
currentFlashHeadIndex = 0;
// 激活精灵渲染器
if (flashHeadSpriteRenderer != null)
{
flashHeadSpriteRenderer.gameObject.SetActive(true);
flashHeadSpriteRenderer.color = new Color(1, 1, 1, 1); // 确保初始alpha为0
}
if (flashBackgroundSpriteRenderer != null)
{
flashBackgroundSpriteRenderer.gameObject.SetActive(true);
flashBackgroundSpriteRenderer.color = new Color(0, 0, 0, 1f); // 确保初始alpha为0
}
// 设置ECG为直线
if (cablePanel != null)
{
cablePanel.SetWaveType(RobotECGWave.WaveType.Flatline);
}
// 创建指定次数的闪烁
for (int i = 0; i < flashCount; i++)
{
flashSequence.AppendCallback(() =>
{
// 设置背景颜色:第1、3张为黑,第2张为白
StartCoroutine(CameraKit.Instance.ShakeCamera(flashDuration, strength, vibrate));
if (currentFlashHeadIndex == 1)
{
flashBackgroundSpriteRenderer.color = Color.white;
}
else
{
flashBackgroundSpriteRenderer.color = Color.black;
}
// 切换头部图片
if (flashHeadSprites.Count > 0)
{
flashHeadSpriteRenderer.sprite = flashHeadSprites[currentFlashHeadIndex];
currentFlashHeadIndex = (currentFlashHeadIndex + 1) % flashHeadSprites.Count;
}
});
flashSequence.AppendInterval(flashDuration);
if (i < flashCount - 1)
{
flashSequence.AppendInterval(flashInterval);
}
}
// 最后整体淡出
if (flashHeadSpriteRenderer != null)
{
flashSequence.Append(flashHeadSpriteRenderer.DOFade(0f, flashDuration));
}
if (flashBackgroundSpriteRenderer != null)
{
flashSequence.Join(flashBackgroundSpriteRenderer.DOFade(0f, flashDuration));
}
// 等待序列完成
yield return flashSequence.WaitForCompletion();
// 恢复ECG波形
if (cablePanel != null && originalWaveType.HasValue)
{
cablePanel.SetWaveType(originalWaveType.Value);
flashHeadSpriteRenderer.gameObject.SetActive(false);
flashHeadSpriteRenderer.color = new Color(1, 1, 1, 0);
flashHeadSpriteRenderer.sprite = flashHeadSprites[0];
}
if (flashBackgroundSpriteRenderer != null)
{
flashBackgroundSpriteRenderer.gameObject.SetActive(false);
flashBackgroundSpriteRenderer.color = new Color(0, 0, 0, 0);
}
}
private void UpdateAbnormalState()
{
// 在异常状态下,拉杆会不受控制地震动
if (lever != null)
{
float randomAngle = Mathf.Sin(Time.time * abnormalLeverShakeSpeed) * abnormalLeverShakeAmount;
lever.localRotation = Quaternion.Euler(0, 0, randomAngle);
}
// 更新充能状态
UpdateCharging();
}
public void SetAbnormalState(bool isAbnormal)
{
isAbnormalState = isAbnormal;
if (isAbnormal)
{
ForceClearLeverInteraction();
StartAbnormalEffects();
}
else
{
StopAbnormalEffects();
}
}
private void StartAbnormalEffects()
{
// 设置进度条颜色为红色
if (progressBarFg != null)
{
progressBarFg.color = abnormalProgressBarColor;
}
// 启动面板震动,使用随机参数
if (operationPanel != null)
{
StartCoroutine(RandomPanelShake());
}
// 激活火花特效并添加随机闪烁
if (sparkEffect1 != null)
{
sparkEffect1.SetActive(true);
StartCoroutine(RandomSparkEffect(sparkEffect1));
}
if (sparkEffect2 != null)
{
sparkEffect2.SetActive(true);
StartCoroutine(RandomSparkEffect(sparkEffect2));
}
}
private IEnumerator RandomPanelShake()
{
while (isAbnormalState)
{
// 随机震动参数
float randomAmount = Random.Range(abnormalPanelShakeAmount * 0.5f, abnormalPanelShakeAmount * 1.5f);
float randomSpeed = Random.Range(abnormalPanelShakeSpeed * 0.7f, abnormalPanelShakeSpeed * 1.3f);
float randomDuration = Random.Range(0.2f, 0.5f);
if (abnormalPanelShakeTweener != null)
{
abnormalPanelShakeTweener.Kill();
}
abnormalPanelShakeTweener = operationPanel.DOShakePosition(
randomDuration,
randomAmount,
vibrate,
randomSpeed,
false,
false
).SetEase(Ease.Linear);
yield return new WaitForSeconds(randomDuration);
}
}
private IEnumerator RandomSparkEffect(GameObject sparkEffect)
{
while (isAbnormalState)
{
// 随机闪烁间隔
float randomInterval = Random.Range(0.1f, 0.3f);
sparkEffect.SetActive(!sparkEffect.activeSelf);
yield return new WaitForSeconds(randomInterval);
}
}
private void StopAbnormalEffects()
{
// 恢复进度条颜色
if (progressBarFg != null)
{
progressBarFg.color = normalProgressBarColor;
}
// 停止面板震动
if (abnormalPanelShakeTweener != null)
{
abnormalPanelShakeTweener.Kill();
}
// 停止拉杆震动
if (abnormalLeverShakeTweener != null)
{
abnormalLeverShakeTweener.Kill();
}
// 关闭火花特效
if (sparkEffect1 != null) sparkEffect1.SetActive(false);
if (sparkEffect2 != null) sparkEffect2.SetActive(false);
}
// 自动充能并释放
public IEnumerator AutoChargeAndRelease(float duration = 1f)
{
bool originalAbnormalState = isAbnormalState;
isAbnormalState = false;
_leverInputLocked = true;
ForceClearLeverInteraction();
// 设置杆的角度
targetLeverAngle = maxLeverAngle;
currentLeverAngle = maxLeverAngle;
lever.localRotation = Quaternion.Euler(0, 0, -maxLeverAngle);
// 开始充能
isCharging = true;
StartCharging();
// 计算需要的充能速度
float targetProgress = progressBar.MaxValue;
float chargeSpeed = targetProgress / duration;
float originalProgressIncreaseSpeed = progressIncreaseSpeed;
progressIncreaseSpeed = chargeSpeed;
// 等待充能完成
float startTime = Time.time;
while (Time.time - startTime < duration)
{
UpdateCharging();
yield return null;
}
// 恢复原始设置
progressIncreaseSpeed = originalProgressIncreaseSpeed;
isCharging = false;
_leverInputLocked = false;
// 重置杆的角度
targetLeverAngle = 0f;
ResetProgress();
// 恢复异常状态
isAbnormalState = originalAbnormalState;
}
// 使用默认参数的自动充能方法
public IEnumerator AutoChargeAndRelease()
{
yield return AutoChargeAndRelease(autoChargeDuration);
}
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();
}
if (flashSequence != null)
{
flashSequence.Kill();
}
if (deviceShakeTweener != null)
{
deviceShakeTweener.Kill();
}
if (abnormalLeverShakeTweener != null)
{
abnormalLeverShakeTweener.Kill();
}
if (abnormalPanelShakeTweener != null)
{
abnormalPanelShakeTweener.Kill();
}
}
// 设置系统电源状态
public void SetSystemPower(bool isOn)
{
isSystemOn = isOn;
// 更新灯光状态
if (isSystemOn)
{
if (flashHeadSpriteRenderer != null)
{
flashHeadSpriteRenderer.gameObject.SetActive(true);
flashHeadSpriteRenderer.color = new Color(1, 1, 1, 1);
}
if (flashBackgroundSpriteRenderer != null)
{
flashBackgroundSpriteRenderer.gameObject.SetActive(true);
flashBackgroundSpriteRenderer.color = new Color(0, 0, 0, 1);
}
}
else
{
if (flashHeadSpriteRenderer != null)
{
flashHeadSpriteRenderer.gameObject.SetActive(false);
flashHeadSpriteRenderer.color = new Color(1, 1, 1, 0);
}
if (flashBackgroundSpriteRenderer != null)
{
flashBackgroundSpriteRenderer.gameObject.SetActive(false);
flashBackgroundSpriteRenderer.color = new Color(0, 0, 0, 0);
}
}
}
}
///
/// 电击器拉杆交互桥接:挂在 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;
}