NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/Audio/AudioFadeEffect.cs

250 lines
6.1 KiB
C#
Raw Normal View History

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