using System.Collections; using UnityEngine; using DG.Tweening; using AibisDream.FixSystem; namespace AibisDream.MiniGame.HuoShan.EmotionWave { /// /// 情绪波形管理器 - 用于控制情绪波形的显示、隐藏和进度动画 /// /// 功能: /// - FixSystemCenter 注册/注销 /// - DOTween 显示/隐藏动画 /// - 进度控制:立即设置 + 平滑动画 /// - 平滑追踪:smoothstep lerp 追踪目标进度 /// public class EmotionWaveManager : MonoBehaviour { #region 序列化字段 [Header("References")] [SerializeField] private EmotionWaveController controller; [SerializeField] private Transform containerTransform; [Header("Slider Sync")] [Tooltip("可选:关联 SliderController 以自动同步进度")] [SerializeField] private SliderController sliderController; [Tooltip("是否启用滑片同步(勾选后滑片进度会自动驱动情绪波形进度)")] [SerializeField] private bool enableSliderSync = true; [Header("动画设置")] [SerializeField] private Vector2 hiddenPosition = new Vector2(0f, -600f); [SerializeField] private Vector2 shownPosition = new Vector2(0f, 0f); [SerializeField] private float showDuration = 0.5f; [SerializeField] private float hideDuration = 0.3f; [SerializeField] private Ease showEase = Ease.OutCubic; [SerializeField] private Ease hideEase = Ease.InCubic; [Header("Progress Settings")] [SerializeField] private float lerpSpeed = 4f; [Header("Debug")] [SerializeField] [ReadOnly] private float currentProgress; [SerializeField] [ReadOnly] private float targetProgress; [SerializeField] [ReadOnly] private bool isShown; #endregion #region 私有字段 private Tweener _progressTweener; private string _currentPresetId = "normal"; private AudioSource _audioSource; #endregion #region 预设 public string CurrentPresetId => _currentPresetId; /// /// 切换波形预设(normal / predicted / modified_joke / empty) /// empty 为低存在感待机态,会保留极弱噪波 /// public void SetPreset(string presetId) { if (string.IsNullOrEmpty(presetId)) return; _currentPresetId = presetId; if (controller != null) controller.SetPreset(presetId); } #endregion #region 属性 public bool IsShown => isShown; public float CurrentProgress => currentProgress; public float TargetProgress => targetProgress; #endregion #region 生命周期 private void Awake() { _audioSource = GetComponent(); if (_audioSource == null) { _audioSource = gameObject.AddComponent(); } // 初始化位置为隐藏状态(不控制 scale,由场景/Prefab 决定) if (containerTransform != null) { containerTransform.localPosition = hiddenPosition; } // 注册到 FixSystemCenter FixSystemCenter.SystemDic.Register(this); // 订阅 SliderController 的进度事件 if (sliderController != null && enableSliderSync) { sliderController.onSliderPositionChanged.AddListener(OnSliderPositionChanged); } } private void OnDestroy() { // 清理 DOTween _progressTweener?.Kill(); // 取消订阅 if (sliderController != null) { sliderController.onSliderPositionChanged.RemoveListener(OnSliderPositionChanged); } // 注销 FixSystemCenter.SystemDic.Unregister(); } private void Update() { if (controller == null) return; // smoothstep lerp 追踪目标进度(和 Web 版 lerpSpeed = 4.0 一致) float dt = Time.deltaTime; currentProgress += (targetProgress - currentProgress) * Mathf.Min(1f, dt * lerpSpeed); // 将当前进度传递给 Controller controller.Progress = currentProgress; } #endregion #region 显示/隐藏动画 /// /// 显示情绪波形(DOTween 动画) /// public IEnumerator Show(float duration = -1f) { if (isShown) yield break; float actualDuration = duration > 0 ? duration : showDuration; isShown = true; if (containerTransform != null) { yield return containerTransform.DOLocalMove(shownPosition, actualDuration) .SetEase(showEase) .WaitForCompletion(); } } /// /// 隐藏情绪波形(DOTween 动画) /// public IEnumerator Hide(float duration = -1f) { if (!isShown) yield break; float actualDuration = duration > 0 ? duration : hideDuration; isShown = false; // 停止所有进度动画 _progressTweener?.Kill(); if (containerTransform != null) { yield return containerTransform.DOLocalMove(hiddenPosition, actualDuration) .SetEase(hideEase) .WaitForCompletion(); } } #endregion #region 进度控制 /// /// 立即设置进度(不等待) /// public void SetProgress(float value) { _progressTweener?.Kill(); targetProgress = Mathf.Clamp01(value); currentProgress = targetProgress; } /// /// 动画到指定进度(DOTween 驱动 targetProgress) /// public IEnumerator AnimateToProgress(float target, float duration) { _progressTweener?.Kill(); target = Mathf.Clamp01(target); // 使用 DOTween.To 驱动 targetProgress _progressTweener = DOTween.To( () => targetProgress, x => targetProgress = x, target, duration ).SetEase(Ease.InOutCubic); yield return _progressTweener.WaitForCompletion(); } #endregion #region Slider 同步 /// /// 响应 SliderController 的位置变化事件 /// private void OnSliderPositionChanged(float normalizedPosition) { if (!enableSliderSync) return; // 滑片进度直接驱动 targetProgress(平滑追踪会在 Update 中处理) targetProgress = Mathf.Clamp01(normalizedPosition); } /// /// 启用/禁用滑片同步 /// public void SetSliderSyncEnabled(bool enabled) { enableSliderSync = enabled; } #endregion #region 辅助方法 [System.Serializable] private class ReadOnlyAttribute : PropertyAttribute { } #endregion } }