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

214 lines
5.9 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 空间音效和位置跟随,与播放逻辑解耦
/// </summary>
public class AudioSpatialController
{
#region Fields
private Transform _audioTransform; // 音频对象的 Transform
private GameObject _followTarget; // 跟随的目标对象
private AudioSource _audioSource; // AudioSource 引用
private bool _is3DEnabled; // 是否启用 3D 音效
#endregion
#region Properties
/// <summary>
/// 是否启用 3D 音效
/// </summary>
public bool Is3DEnabled => _is3DEnabled;
/// <summary>
/// 当前跟随的目标
/// </summary>
public GameObject FollowTarget => _followTarget;
/// <summary>
/// 当前位置
/// </summary>
public Vector3 Position
{
get => _audioTransform != null ? _audioTransform.position : Vector3.zero;
set
{
if (_audioTransform != null)
_audioTransform.position = value;
}
}
#endregion
#region Constructor
/// <summary>
/// 创建空间音频控制器
/// </summary>
/// <param name="audioTransform">音频对象的 Transform</param>
/// <param name="audioSource">AudioSource 组件</param>
public AudioSpatialController(Transform audioTransform, AudioSource audioSource)
{
_audioTransform = audioTransform;
_audioSource = audioSource;
_is3DEnabled = false;
}
#endregion
#region Public Methods
/// <summary>
/// 启用 3D 空间音效
/// </summary>
/// <param name="maxDistance">最大听音距离</param>
public void Enable3D(float maxDistance = 150f)
{
if (_audioSource == null)
return;
_audioSource.spatialBlend = 1f;
_audioSource.dopplerLevel = 0f;
_audioSource.rolloffMode = AudioRolloffMode.Linear;
_audioSource.maxDistance = maxDistance;
_is3DEnabled = true;
}
/// <summary>
/// 禁用 3D 空间音效(改为 2D
/// </summary>
public void Disable3D()
{
if (_audioSource == null)
return;
_audioSource.spatialBlend = 0f;
_is3DEnabled = false;
}
/// <summary>
/// 设置跟随目标(自动启用 3D
/// </summary>
/// <param name="target">要跟随的目标对象null 表示停止跟随</param>
/// <param name="maxDistance">最大听音距离</param>
public void SetFollowTarget(GameObject target, float maxDistance = 150f)
{
_followTarget = target;
if (target != null)
{
// 有目标,启用 3D 并立即同步位置
Enable3D(maxDistance);
if (_audioTransform != null)
{
_audioTransform.position = target.transform.position;
}
}
else
{
// 无目标,禁用 3D
Disable3D();
}
}
/// <summary>
/// 设置静态位置(不跟随对象)
/// </summary>
/// <param name="position">世界坐标位置</param>
/// <param name="enable3D">是否启用 3D 音效</param>
/// <param name="maxDistance">最大听音距离</param>
public void SetStaticPosition(Vector3 position, bool enable3D = true, float maxDistance = 150f)
{
_followTarget = null;
if (_audioTransform != null)
{
_audioTransform.position = position;
}
if (enable3D)
{
Enable3D(maxDistance);
}
else
{
Disable3D();
}
}
/// <summary>
/// 更新位置跟随(在 Update 循环中调用)
/// </summary>
public void Update()
{
if (_followTarget != null && _audioTransform != null)
{
_audioTransform.position = _followTarget.transform.position;
}
}
/// <summary>
/// 重置到初始状态
/// </summary>
public void Reset()
{
_followTarget = null;
Disable3D();
if (_audioTransform != null)
{
_audioTransform.localPosition = Vector3.zero;
}
}
/// <summary>
/// 配置 3D 音效参数
/// </summary>
/// <param name="spatialBlend">空间混合度 (0=2D, 1=3D)</param>
/// <param name="dopplerLevel">多普勒效应强度</param>
/// <param name="rolloffMode">衰减模式</param>
/// <param name="maxDistance">最大距离</param>
/// <param name="minDistance">最小距离</param>
public void Configure3D(
float spatialBlend = 1f,
float dopplerLevel = 0f,
AudioRolloffMode rolloffMode = AudioRolloffMode.Linear,
float maxDistance = 150f,
float minDistance = 1f)
{
if (_audioSource == null)
return;
_audioSource.spatialBlend = Mathf.Clamp01(spatialBlend);
_audioSource.dopplerLevel = Mathf.Max(0f, dopplerLevel);
_audioSource.rolloffMode = rolloffMode;
_audioSource.maxDistance = Mathf.Max(minDistance, maxDistance);
_audioSource.minDistance = Mathf.Max(0f, minDistance);
_is3DEnabled = spatialBlend > 0f;
}
#endregion
#region Debug
/// <summary>
/// 获取调试信息
/// </summary>
public string GetDebugInfo()
{
string targetInfo = _followTarget != null ? _followTarget.name : "None";
string posInfo = _audioTransform != null ? _audioTransform.position.ToString("F2") : "N/A";
return $"SpatialController: 3D={_is3DEnabled}, " +
$"Following={targetInfo}, " +
$"Position={posInfo}, " +
$"SpatialBlend={(_audioSource != null ? _audioSource.spatialBlend : 0f):F2}";
}
#endregion
}