using UnityEngine; /// /// 音频空间控制器 /// 职责:管理 3D 空间音效和位置跟随,与播放逻辑解耦 /// public class AudioSpatialController { #region Fields private Transform _audioTransform; // 音频对象的 Transform private GameObject _followTarget; // 跟随的目标对象 private AudioSource _audioSource; // AudioSource 引用 private bool _is3DEnabled; // 是否启用 3D 音效 #endregion #region Properties /// /// 是否启用 3D 音效 /// public bool Is3DEnabled => _is3DEnabled; /// /// 当前跟随的目标 /// public GameObject FollowTarget => _followTarget; /// /// 当前位置 /// public Vector3 Position { get => _audioTransform != null ? _audioTransform.position : Vector3.zero; set { if (_audioTransform != null) _audioTransform.position = value; } } #endregion #region Constructor /// /// 创建空间音频控制器 /// /// 音频对象的 Transform /// AudioSource 组件 public AudioSpatialController(Transform audioTransform, AudioSource audioSource) { _audioTransform = audioTransform; _audioSource = audioSource; _is3DEnabled = false; } #endregion #region Public Methods /// /// 启用 3D 空间音效 /// /// 最大听音距离 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; } /// /// 禁用 3D 空间音效(改为 2D) /// public void Disable3D() { if (_audioSource == null) return; _audioSource.spatialBlend = 0f; _is3DEnabled = false; } /// /// 设置跟随目标(自动启用 3D) /// /// 要跟随的目标对象,null 表示停止跟随 /// 最大听音距离 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(); } } /// /// 设置静态位置(不跟随对象) /// /// 世界坐标位置 /// 是否启用 3D 音效 /// 最大听音距离 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(); } } /// /// 更新位置跟随(在 Update 循环中调用) /// public void Update() { if (_followTarget != null && _audioTransform != null) { _audioTransform.position = _followTarget.transform.position; } } /// /// 重置到初始状态 /// public void Reset() { _followTarget = null; Disable3D(); if (_audioTransform != null) { _audioTransform.localPosition = Vector3.zero; } } /// /// 配置 3D 音效参数 /// /// 空间混合度 (0=2D, 1=3D) /// 多普勒效应强度 /// 衰减模式 /// 最大距离 /// 最小距离 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 /// /// 获取调试信息 /// 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 }