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

221 lines
6.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using UnityEngine;
/// <summary>
/// 音频空间控制器(精简版)
/// 职责:管理 3D 空间音效和位置跟随
/// 设计:最小化字段,直接操作 AudioSource
/// </summary>
public class AudioSpatialController
{
#region Constants
private const float DEFAULT_MAX_DISTANCE = 150f;
private const float DEFAULT_MIN_DISTANCE = 1f;
#endregion
#region Fields
private readonly Transform _audioTransform;
private readonly AudioSource _audioSource;
private GameObject _followTarget;
#endregion
#region Properties
/// <summary>
/// 是否启用 3D 音效(从 AudioSource 读取)
/// </summary>
public bool Is3DEnabled => _audioSource != null && _audioSource.spatialBlend > 0f;
/// <summary>
/// 当前跟随的目标
/// </summary>
public GameObject FollowTarget => _followTarget;
/// <summary>
/// 是否正在跟随对象
/// </summary>
public bool IsFollowing => _followTarget != null;
/// <summary>
/// 当前位置
/// </summary>
public Vector3 Position
{
get => _audioTransform?.position ?? Vector3.zero;
set
{
if (_audioTransform != null)
_audioTransform.position = value;
}
}
#endregion
#region Constructor
/// <summary>
/// 创建空间音频控制器
/// </summary>
public AudioSpatialController(Transform audioTransform, AudioSource audioSource)
{
_audioTransform = audioTransform;
_audioSource = audioSource;
}
#endregion
#region Public Methods - 3D Control
/// <summary>
/// 设置 3D 模式(统一接口)
/// </summary>
/// <param name="enable">是否启用 3D</param>
/// <param name="maxDistance">最大听音距离</param>
public void Set3D(bool enable, float maxDistance = DEFAULT_MAX_DISTANCE)
{
if (_audioSource == null) return;
if (enable)
{
_audioSource.spatialBlend = 1f;
_audioSource.dopplerLevel = 0f;
_audioSource.rolloffMode = AudioRolloffMode.Linear;
_audioSource.minDistance = DEFAULT_MIN_DISTANCE;
_audioSource.maxDistance = maxDistance;
}
else
{
_audioSource.spatialBlend = 0f;
}
}
/// <summary>
/// 启用 3D 空间音效
/// </summary>
public void Enable3D(float maxDistance = DEFAULT_MAX_DISTANCE)
=> Set3D(true, maxDistance);
/// <summary>
/// 禁用 3D 空间音效(改为 2D
/// </summary>
public void Disable3D()
=> Set3D(false);
#endregion
#region Public Methods - Position Control
/// <summary>
/// 设置跟随目标(自动启用/禁用 3D
/// </summary>
/// <param name="target">跟随目标null 则停止跟随并禁用 3D</param>
/// <param name="maxDistance">最大听音距离</param>
public void SetFollowTarget(GameObject target, float maxDistance = DEFAULT_MAX_DISTANCE)
{
_followTarget = target;
if (target != null)
{
// 立即同步位置并启用 3D
Position = target.transform.position;
Enable3D(maxDistance);
}
else
{
// 停止跟随并禁用 3D
Disable3D();
}
}
/// <summary>
/// 设置静态位置(不跟随,可选择是否 3D
/// </summary>
/// <param name="position">世界坐标位置</param>
/// <param name="enable3D">是否启用 3D 音效</param>
/// <param name="maxDistance">最大听音距离</param>
public void SetStaticPosition(Vector3 position, bool enable3D = true, float maxDistance = DEFAULT_MAX_DISTANCE)
{
_followTarget = null;
Position = position;
Set3D(enable3D, maxDistance);
}
/// <summary>
/// 更新位置跟随(在 Update 循环中调用)
/// </summary>
public void Update()
{
if (_followTarget != null && _audioTransform != null)
{
_audioTransform.position = _followTarget.transform.position;
}
}
#endregion
#region Public Methods - Advanced
/// <summary>
/// 高级配置:自定义所有 3D 参数
/// </summary>
/// <param name="spatialBlend">空间混合度 (0=2D, 1=3D)</param>
/// <param name="minDistance">最小距离(全音量范围)</param>
/// <param name="maxDistance">最大距离(衰减到 0</param>
/// <param name="rolloffMode">衰减模式</param>
/// <param name="dopplerLevel">多普勒效应强度</param>
public void ConfigureAdvanced(
float spatialBlend,
float minDistance = DEFAULT_MIN_DISTANCE,
float maxDistance = DEFAULT_MAX_DISTANCE,
AudioRolloffMode rolloffMode = AudioRolloffMode.Linear,
float dopplerLevel = 0f)
{
if (_audioSource == null) return;
_audioSource.spatialBlend = Mathf.Clamp01(spatialBlend);
_audioSource.minDistance = Mathf.Max(0.01f, minDistance);
_audioSource.maxDistance = Mathf.Max(minDistance, maxDistance);
_audioSource.rolloffMode = rolloffMode;
_audioSource.dopplerLevel = Mathf.Max(0f, dopplerLevel);
}
/// <summary>
/// 重置到初始状态2D、不跟随、位置归零
/// </summary>
public void Reset()
{
_followTarget = null;
Disable3D();
if (_audioTransform != null)
{
_audioTransform.localPosition = Vector3.zero;
}
}
#endregion
#region Debug
/// <summary>
/// 获取调试信息
/// </summary>
public override string ToString()
{
if (_audioSource == null)
return "SpatialController: [Invalid]";
return $"SpatialController: " +
$"Mode={(Is3DEnabled ? "3D" : "2D")}, " +
$"Following={(_followTarget?.name ?? "None")}, " +
$"Position={Position:F1}, " +
$"SpatialBlend={_audioSource.spatialBlend:F2}, " +
$"MaxDist={_audioSource.maxDistance:F0}";
}
#endregion
}