Files
aibis-dream/Assets/Scripts/FixSystemNew/Open/ShockSystem.cs
T

887 lines
31 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
/// <summary>
/// 电击器系统。拉杆交互通过 EventTriggerEx 统一管理,支持 EventSystemEx.isLocked 与 IInteraction
/// 光标由 EventTriggerEx → EventSystemEx → CursorManager 自动驱动。
/// </summary>
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<Sprite> 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();
}
/// <summary>
/// 为拉杆挂接 ShockLeverInteractionBridge + EventTriggerEx(对齐 CrankController)。
/// 悬停光标另用 LateUpdate 射线校正:指针 Collider 细长且会旋转,EventSystem 易丢 PointerExit。
/// </summary>
private void EnsureLeverInteraction()
{
if (lever == null) return;
var leverGo = lever.gameObject;
if (leverGo.GetComponent<Collider2D>() == null)
{
#if UNITY_EDITOR
Debug.LogWarning("[ShockSystem] 拉杆未找到 Collider2D!请添加 Collider2D 以接入交互与光标。", this);
#endif
return;
}
_leverBridge = leverGo.GetComponent<ShockLeverInteractionBridge>();
if (_leverBridge == null)
_leverBridge = leverGo.AddComponent<ShockLeverInteractionBridge>();
_eventTrigger = leverGo.GetComponent<EventTriggerEx>();
if (_eventTrigger == null)
_eventTrigger = leverGo.AddComponent<EventTriggerEx>();
_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;
}
/// <summary>
/// 以射线结果校正悬停光标,弥补细长旋转 Collider 丢失 PointerExit 的情况。
/// </summary>
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);
}
/// <summary>无 EventTriggerEx 时回退到 Input + Raycast。</summary>
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 > 0 && !isCharging)
{
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<CablePanel>();
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);
}
}
}
}
/// <summary>
/// 电击器拉杆交互桥接:挂在 Collider 所在子物体上,将 IInteraction 转交给父级 ShockSystem(对齐 CrankInteractionBridge)。
/// </summary>
public class ShockLeverInteractionBridge : MonoBehaviour, IInteraction
{
private ShockSystem _shockSystem;
private void Awake()
{
_shockSystem = GetComponentInParent<ShockSystem>();
}
public bool IsActive => _shockSystem?.IsActive ?? true;
public bool IsAvailable => _shockSystem?.IsAvailable ?? true;
public GameObject GetGameObject() => gameObject;
}