using UnityEngine;
///
/// 音频淡入淡出效果类(简化版)
/// 职责:管理音频的淡入淡出效果,与播放逻辑解耦
/// 设计:使用状态机模式,单一计时器,逻辑清晰
///
public class AudioFadeEffect
{
#region Enums
///
/// 淡入淡出状态
///
public enum FadeState
{
None, // 无效果
FadingIn, // 正在淡入
FadingOut, // 正在淡出
}
#endregion
#region Fields
private FadeState _state = FadeState.None;
private float _elapsedTime = 0f; // 当前状态经过的时间
private float _fadeInDuration = 4f; // 淡入时长(秒)
private float _fadeOutDuration = 4f; // 淡出时长(秒)
#endregion
#region Properties
///
/// 当前淡入淡出系数 (0-1)
///
public float FadeValue { get; private set; } = 1f;
///
/// 当前状态
///
public FadeState State => _state;
///
/// 是否正在淡入
///
public bool IsFadingIn => _state == FadeState.FadingIn;
///
/// 是否正在淡出
///
public bool IsFadingOut => _state == FadeState.FadingOut;
///
/// 是否有任何效果激活
///
public bool IsActive => _state != FadeState.None;
///
/// 淡入时长(秒)
///
public float FadeInDuration
{
get => _fadeInDuration;
set => _fadeInDuration = Mathf.Max(0.01f, value);
}
///
/// 淡出时长(秒)
///
public float FadeOutDuration
{
get => _fadeOutDuration;
set => _fadeOutDuration = Mathf.Max(0.01f, value);
}
#endregion
#region Constructor
///
/// 创建淡入淡出效果
///
/// 淡入时长(秒)
/// 淡出时长(秒)
public AudioFadeEffect(float fadeInDuration = 4f, float fadeOutDuration = 4f)
{
_fadeInDuration = Mathf.Max(0.01f, fadeInDuration);
_fadeOutDuration = Mathf.Max(0.01f, fadeOutDuration);
FadeValue = 1f;
}
#endregion
#region Public Methods
///
/// 开始淡入效果
///
/// 淡入时长(秒),null 则使用默认值
public void StartFadeIn(float? duration = null)
{
if (duration.HasValue)
{
_fadeInDuration = Mathf.Max(0.01f, duration.Value);
}
_state = FadeState.FadingIn;
_elapsedTime = 0f;
FadeValue = 0f;
}
///
/// 开始淡出效果
///
/// 淡出时长(秒),null 则使用默认值
/// 如果已经在淡出中则返回 false
public bool StartFadeOut(float? duration = null)
{
if (_state == FadeState.FadingOut)
return false;
if (duration.HasValue)
{
_fadeOutDuration = Mathf.Max(0.01f, duration.Value);
}
_state = FadeState.FadingOut;
_elapsedTime = 0f;
// FadeValue 保持当前值,从当前音量开始淡出
return true;
}
///
/// 停止所有淡入淡出效果
///
public void Stop()
{
_state = FadeState.None;
_elapsedTime = 0f;
FadeValue = 1f;
}
///
/// 重置到初始状态(无淡入淡出)
///
public void Reset()
{
Stop();
}
///
/// 更新淡入淡出效果
///
/// 时间增量
/// 是否应该停止播放(淡出完成)
public bool Update(float deltaTime)
{
if (_state == FadeState.None)
{
FadeValue = 1f;
return false;
}
_elapsedTime += deltaTime;
switch (_state)
{
case FadeState.FadingIn:
return UpdateFadeIn();
case FadeState.FadingOut:
return UpdateFadeOut();
default:
return false;
}
}
///
/// 获取当前应用淡入淡出后的音量
///
/// 原始音量
/// 应用淡入淡出系数后的音量
public float ApplyFade(float originalVolume)
{
return originalVolume * FadeValue;
}
#endregion
#region Private Methods
///
/// 更新淡入
///
private bool UpdateFadeIn()
{
if (_elapsedTime >= _fadeInDuration)
{
// 淡入完成
FadeValue = 1f;
_state = FadeState.None;
return false;
}
// 计算淡入进度
FadeValue = Mathf.Clamp01(_elapsedTime / _fadeInDuration);
return false;
}
///
/// 更新淡出
///
private bool UpdateFadeOut()
{
if (_elapsedTime >= _fadeOutDuration)
{
// 淡出完成
FadeValue = 0f;
_state = FadeState.None;
return true; // 通知调用者应该停止播放
}
// 计算淡出进度(从当前值淡出到0)
float progress = _elapsedTime / _fadeOutDuration;
FadeValue = Mathf.Lerp(FadeValue, 0f, progress);
return false;
}
#endregion
#region Debug
///
/// 获取调试信息
///
public string GetDebugInfo()
{
return $"FadeEffect: State={_state}, Value={FadeValue:F2}, " +
$"Elapsed={_elapsedTime:F2}s, " +
$"Durations(In={_fadeInDuration:F1}s, Out={_fadeOutDuration:F1}s)";
}
#endregion
}