empty 改为极弱噪波待机态;增加预设切换 crossfade 与 flash 效果; noiseOnlyBlend 支持纯噪波渲染;两段式归一化使 fillAmount=1 正确填满;switch_emotion_wave_config 支持 progress 参数。 Made-with: Cursor
246 lines
7.3 KiB
C#
246 lines
7.3 KiB
C#
using System.Collections;
|
||
using UnityEngine;
|
||
using DG.Tweening;
|
||
using AibisDream.FixSystem;
|
||
|
||
namespace AibisDream.MiniGame.HuoShan.EmotionWave
|
||
{
|
||
/// <summary>
|
||
/// 情绪波形管理器 - 用于控制情绪波形的显示、隐藏和进度动画
|
||
///
|
||
/// 功能:
|
||
/// - FixSystemCenter 注册/注销
|
||
/// - DOTween 显示/隐藏动画
|
||
/// - 进度控制:立即设置 + 平滑动画
|
||
/// - 平滑追踪:smoothstep lerp 追踪目标进度
|
||
/// </summary>
|
||
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;
|
||
|
||
/// <summary>
|
||
/// 切换波形预设(normal / predicted / modified_joke / empty)
|
||
/// empty 为低存在感待机态,会保留极弱噪波
|
||
/// </summary>
|
||
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<AudioSource>();
|
||
if (_audioSource == null)
|
||
{
|
||
_audioSource = gameObject.AddComponent<AudioSource>();
|
||
}
|
||
|
||
// 初始化位置为隐藏状态(不控制 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<EmotionWaveManager>();
|
||
}
|
||
|
||
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 显示/隐藏动画
|
||
|
||
/// <summary>
|
||
/// 显示情绪波形(DOTween 动画)
|
||
/// </summary>
|
||
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();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏情绪波形(DOTween 动画)
|
||
/// </summary>
|
||
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 进度控制
|
||
|
||
/// <summary>
|
||
/// 立即设置进度(不等待)
|
||
/// </summary>
|
||
public void SetProgress(float value)
|
||
{
|
||
_progressTweener?.Kill();
|
||
targetProgress = Mathf.Clamp01(value);
|
||
currentProgress = targetProgress;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 动画到指定进度(DOTween 驱动 targetProgress)
|
||
/// </summary>
|
||
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 同步
|
||
|
||
/// <summary>
|
||
/// 响应 SliderController 的位置变化事件
|
||
/// </summary>
|
||
private void OnSliderPositionChanged(float normalizedPosition)
|
||
{
|
||
if (!enableSliderSync) return;
|
||
|
||
// 滑片进度直接驱动 targetProgress(平滑追踪会在 Update 中处理)
|
||
targetProgress = Mathf.Clamp01(normalizedPosition);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启用/禁用滑片同步
|
||
/// </summary>
|
||
public void SetSliderSyncEnabled(bool enabled)
|
||
{
|
||
enableSliderSync = enabled;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 辅助方法
|
||
|
||
[System.Serializable]
|
||
private class ReadOnlyAttribute : PropertyAttribute { }
|
||
|
||
#endregion
|
||
}
|
||
}
|