214 lines
5.9 KiB
C#
214 lines
5.9 KiB
C#
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
|
||
}
|
||
|