using UnityEngine; using UnityEngine.UI; using DG.Tweening; using TMPro; using RainbowArt.CleanFlatUI; using System.Collections.Generic; using AibisDream.Framework; using UnityEngine.EventSystems; using AibisDream.FixSystem; using System.Collections; using AibisDream; // 添加 SpriteFlashSystem 的命名空间 public class ShockSystem : MonoBehaviour { [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; // 异常状态下进度条颜色 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; // 正常状态下进度条颜色 // 公共访问器 public float FlashDuration => flashDuration; public float FlashInterval => flashInterval; public int FlashCount => flashCount; private void Awake() { // 注册 FixSystemCenter.SystemDic.Register(this); } 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 { HandleLeverInput(); UpdateLeverRotation(); UpdateCharging(); } } private void HandleLeverInput() { 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) { 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(); } } 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(); } } else { // 杆自动回弹 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(); } } } 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() { // 开始进度条平滑下降 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; // 计算震动强度 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(); } // 获取ECG波形组件 var lightSystem = FixSystemCenter.SystemDic.Get(); var originalWaveType = lightSystem?.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 (lightSystem != null) { lightSystem.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 (lightSystem != null && originalWaveType.HasValue) { lightSystem.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) { // 启动异常状态效果 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; // 禁用玩家输入 bool originalIsDraggingLever = isDraggingLever; isDraggingLever = false; // 设置杆的角度 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; isDraggingLever = originalIsDraggingLever; // 重置杆的角度 targetLeverAngle = 0f; ResetProgress(); // 恢复异常状态 isAbnormalState = originalAbnormalState; } // 使用默认参数的自动充能方法 public IEnumerator AutoChargeAndRelease() { yield return AutoChargeAndRelease(autoChargeDuration); } private void OnDestroy() { 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); } } } }