444 lines
15 KiB
C#
444 lines
15 KiB
C#
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 operationPanel; // 操作面板
|
|
[SerializeField] private SliderTransition powerSlider; // 力度滑块
|
|
[SerializeField] private ProgressBarGridLinear progressBar; // 进度条
|
|
[SerializeField] private Transform sliderBar; // 推杆的杆部分
|
|
[SerializeField] private SpriteRenderer flashHeadSpriteRenderer; // 头部闪烁精灵渲染器
|
|
[SerializeField] private SpriteRenderer flashBackgroundSpriteRenderer; // 背景闪烁精灵渲染器
|
|
[SerializeField] private SpriteRenderer flashSpriteRenderer;
|
|
[SerializeField] private List<Sprite> flashHeadSprites; // 头部闪烁精灵列表
|
|
[SerializeField] private SpriteFlashSystem spriteFlashSystem; // Sprite闪烁系统
|
|
[Header("Settings")]
|
|
[SerializeField] private Vector3 shockDeviceTargetPos; // 电击器目标位置
|
|
[SerializeField] private Vector3 operationPanelTargetPos; // 操作面板目标位置
|
|
[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; // 自动充能持续时间
|
|
|
|
private bool isCharging = false;
|
|
private float currentProgress = 0f;
|
|
private Slider baseSlider; // 基础Slider组件
|
|
private Tweener progressTweener; // 用于存储进度条动画
|
|
private Sequence flashSequence; // 用于存储闪烁动画序列
|
|
private int currentFlashHeadIndex = 0; // 当前闪烁头部精灵索引
|
|
private Tweener sliderReturnTweener; // 用于存储滑块回弹动画
|
|
private float lastVibrateTime = 0f; // 上次震动时间
|
|
private Vector3 deviceOriginalPos; // 电击器原始位置
|
|
private Tweener deviceShakeTweener; // 电击器震动动画
|
|
|
|
// 公共访问器
|
|
public float FlashDuration => flashDuration;
|
|
public float FlashInterval => flashInterval;
|
|
public int FlashCount => flashCount;
|
|
|
|
private void Awake()
|
|
{
|
|
// 注册
|
|
FixSystemCenter.SystemDic.Register(this);
|
|
}
|
|
|
|
|
|
private void Start()
|
|
{
|
|
// 保存电击器原始位置
|
|
if (shockDevice != null)
|
|
{
|
|
deviceOriginalPos = shockDevice.localPosition;
|
|
}
|
|
|
|
// 获取基础Slider组件
|
|
baseSlider = powerSlider.GetComponent<Slider>();
|
|
if (baseSlider != null)
|
|
{
|
|
baseSlider.onValueChanged.AddListener(OnSliderValueChanged);
|
|
|
|
// 添加EventTrigger组件
|
|
EventTrigger trigger = baseSlider.gameObject.GetComponent<EventTrigger>();
|
|
if (trigger == null)
|
|
{
|
|
trigger = baseSlider.gameObject.AddComponent<EventTrigger>();
|
|
}
|
|
|
|
// 添加结束拖拽事件
|
|
EventTrigger.Entry entry = new EventTrigger.Entry();
|
|
entry.eventID = EventTriggerType.EndDrag;
|
|
entry.callback.AddListener((data) => { OnSliderEndDrag(); });
|
|
trigger.triggers.Add(entry);
|
|
}
|
|
|
|
// 初始化闪烁精灵
|
|
if (flashHeadSpriteRenderer != null)
|
|
{
|
|
flashHeadSpriteRenderer.gameObject.SetActive(false);
|
|
Color color = flashHeadSpriteRenderer.color;
|
|
color.a = 0;
|
|
flashHeadSpriteRenderer.color = color;
|
|
}
|
|
|
|
if (flashBackgroundSpriteRenderer != null)
|
|
{
|
|
flashBackgroundSpriteRenderer.gameObject.SetActive(false);
|
|
Color color = flashBackgroundSpriteRenderer.color;
|
|
color.a = 0;
|
|
color = Color.black;
|
|
flashBackgroundSpriteRenderer.color = color;
|
|
}
|
|
|
|
|
|
//InitializeShock();
|
|
}
|
|
|
|
// 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 move1 = shockDevice.DOLocalMove(shockDeviceTargetPos, moveDuration);
|
|
var move2 = operationPanel.DOLocalMove(operationPanelTargetPos, moveDuration);
|
|
powerSlider.EnableSliderInteraction();
|
|
|
|
yield return move1.WaitForCompletion();
|
|
yield return move2.WaitForCompletion();
|
|
}
|
|
|
|
public IEnumerator StopShock()
|
|
{
|
|
var move1 = shockDevice.DOLocalMove(deviceOriginalPos, moveDuration);
|
|
var move2 = operationPanel.DOLocalMove(operationPanelTargetPos, moveDuration);
|
|
powerSlider.DisableSliderInteraction();
|
|
|
|
yield return move1.WaitForCompletion();
|
|
yield return move2.WaitForCompletion();
|
|
}
|
|
|
|
private void OnSliderValueChanged(float value)
|
|
{
|
|
if(value > 0)
|
|
{
|
|
sliderBar.localPosition = new Vector3(0, -89, 0);
|
|
}
|
|
else
|
|
{
|
|
sliderBar.localPosition = new Vector3(0, 80, 0);
|
|
// 停止电击器震动
|
|
if (deviceShakeTweener != null)
|
|
{
|
|
deviceShakeTweener.Kill();
|
|
deviceShakeTweener = null;
|
|
}
|
|
}
|
|
// 如果滑块值大于0,取消回弹动画
|
|
if (value > 0 && sliderReturnTweener != null)
|
|
{
|
|
sliderReturnTweener.Kill();
|
|
sliderReturnTweener = null;
|
|
sliderBar.localPosition = new Vector3(0, -89, 0);
|
|
}
|
|
|
|
if (value > 0)
|
|
{
|
|
if (!isCharging)
|
|
{
|
|
isCharging = true;
|
|
StartCharging();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isCharging)
|
|
{
|
|
isCharging = false;
|
|
// 只有在进度条满时才触发闪烁效果
|
|
if (currentProgress >= progressBar.MaxValue)
|
|
{
|
|
// 触发 Yarn 节点来决定使用哪种效果
|
|
DialogController.Instance.StartDialogNode(shockEffectNode);
|
|
}
|
|
// 重置进度条
|
|
ResetProgress();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnSliderEndDrag()
|
|
{
|
|
// 如果滑块值大于0,开始回弹动画
|
|
if (baseSlider.value > 0)
|
|
{
|
|
if (sliderReturnTweener != null)
|
|
{
|
|
sliderReturnTweener.Kill();
|
|
}
|
|
|
|
sliderReturnTweener = DOTween.To(
|
|
() => baseSlider.value,
|
|
x => baseSlider.value = x,
|
|
0f,
|
|
0.3f // 回弹动画持续时间
|
|
).SetEase(Ease.OutQuad);
|
|
}
|
|
}
|
|
|
|
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 StartCharging()
|
|
{
|
|
if (!isCharging) return;
|
|
|
|
// 根据滑块值计算进度增加速度
|
|
float currentValue = baseSlider.value;
|
|
float speedMultiplier = 1f + (currentValue / maxSliderValue);
|
|
currentProgress += progressIncreaseSpeed * speedMultiplier * Time.deltaTime;
|
|
|
|
// 更新进度条
|
|
int progressValue = Mathf.FloorToInt(currentProgress);
|
|
progressBar.CurrentValue = progressValue;
|
|
|
|
// 计算震动强度
|
|
float progressRatio = Mathf.Min(currentProgress / progressBar.MaxValue, 1f);
|
|
float currentVibrateStrength = Mathf.Lerp(minVibrateStrength, maxVibrateStrength, progressRatio);
|
|
|
|
// 检查是否需要震动
|
|
if (Time.time - lastVibrateTime >= vibrateInterval)
|
|
{
|
|
// 相机震动
|
|
//StartCoroutine(CameraKit.Instance.ShakeCamera(vibrateInterval, currentVibrateStrength, vibrate));
|
|
|
|
// 电击器震动
|
|
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)
|
|
{
|
|
// 继续充电和震动
|
|
DOVirtual.DelayedCall(Time.deltaTime, StartCharging);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// 继续充电
|
|
DOVirtual.DelayedCall(Time.deltaTime, StartCharging);
|
|
}
|
|
}
|
|
|
|
public IEnumerator PlayFlashEffect()
|
|
{
|
|
if (flashSequence != null)
|
|
{
|
|
flashSequence.Kill();
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// 创建指定次数的闪烁
|
|
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();
|
|
|
|
// 闪烁结束后禁用所有精灵并重置状态
|
|
if (flashHeadSpriteRenderer != null)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
// 自动充能并释放
|
|
public IEnumerator AutoChargeAndRelease(float chargeSpeed = 5f, float duration = 1f)
|
|
{
|
|
// 设置滑块值
|
|
baseSlider.value = maxSliderValue;
|
|
|
|
// 等待充能完成
|
|
float startTime = Time.time;
|
|
while (Time.time - startTime < duration)
|
|
{
|
|
// 使用指定的充能速度
|
|
currentProgress += chargeSpeed * Time.deltaTime;
|
|
progressBar.CurrentValue = Mathf.FloorToInt(currentProgress);
|
|
yield return null;
|
|
}
|
|
|
|
// 确保进度达到最大值
|
|
currentProgress = progressBar.MaxValue;
|
|
progressBar.CurrentValue = Mathf.FloorToInt(currentProgress);
|
|
|
|
// 触发 Yarn 节点来决定使用哪种效果
|
|
DialogController.Instance.StartDialogNode(shockEffectNode);
|
|
|
|
// 重置滑块
|
|
baseSlider.value = 0;
|
|
ResetProgress();
|
|
}
|
|
|
|
// 使用默认参数的自动充能方法
|
|
public IEnumerator AutoChargeAndRelease()
|
|
{
|
|
yield return AutoChargeAndRelease(autoChargeSpeed, autoChargeDuration);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (progressTweener != null)
|
|
{
|
|
progressTweener.Kill();
|
|
}
|
|
if (flashSequence != null)
|
|
{
|
|
flashSequence.Kill();
|
|
}
|
|
if (sliderReturnTweener != null)
|
|
{
|
|
sliderReturnTweener.Kill();
|
|
}
|
|
if (deviceShakeTweener != null)
|
|
{
|
|
deviceShakeTweener.Kill();
|
|
}
|
|
}
|
|
} |