using UnityEngine; /// /// 音频空间控制器(精简版) /// 职责:管理 3D 空间音效和位置跟随 /// 设计:最小化字段,直接操作 AudioSource /// 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 /// /// 是否启用 3D 音效(从 AudioSource 读取) /// public bool Is3DEnabled => _audioSource != null && _audioSource.spatialBlend > 0f; /// /// 当前跟随的目标 /// public GameObject FollowTarget => _followTarget; /// /// 是否正在跟随对象 /// public bool IsFollowing => _followTarget != null; /// /// 当前位置 /// public Vector3 Position { get => _audioTransform?.position ?? Vector3.zero; set { if (_audioTransform != null) _audioTransform.position = value; } } #endregion #region Constructor /// /// 创建空间音频控制器 /// public AudioSpatialController(Transform audioTransform, AudioSource audioSource) { _audioTransform = audioTransform; _audioSource = audioSource; } #endregion #region Public Methods - 3D Control /// /// 设置 3D 模式(统一接口) /// /// 是否启用 3D /// 最大听音距离 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; } } /// /// 启用 3D 空间音效 /// public void Enable3D(float maxDistance = DEFAULT_MAX_DISTANCE) => Set3D(true, maxDistance); /// /// 禁用 3D 空间音效(改为 2D) /// public void Disable3D() => Set3D(false); #endregion #region Public Methods - Position Control /// /// 设置跟随目标(自动启用/禁用 3D) /// /// 跟随目标,null 则停止跟随并禁用 3D /// 最大听音距离 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(); } } /// /// 设置静态位置(不跟随,可选择是否 3D) /// /// 世界坐标位置 /// 是否启用 3D 音效 /// 最大听音距离 public void SetStaticPosition(Vector3 position, bool enable3D = true, float maxDistance = DEFAULT_MAX_DISTANCE) { _followTarget = null; Position = position; Set3D(enable3D, maxDistance); } /// /// 更新位置跟随(在 Update 循环中调用) /// public void Update() { if (_followTarget != null && _audioTransform != null) { _audioTransform.position = _followTarget.transform.position; } } #endregion #region Public Methods - Advanced /// /// 高级配置:自定义所有 3D 参数 /// /// 空间混合度 (0=2D, 1=3D) /// 最小距离(全音量范围) /// 最大距离(衰减到 0) /// 衰减模式 /// 多普勒效应强度 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); } /// /// 重置到初始状态(2D、不跟随、位置归零) /// public void Reset() { _followTarget = null; Disable3D(); if (_audioTransform != null) { _audioTransform.localPosition = Vector3.zero; } } #endregion #region Debug /// /// 获取调试信息 /// 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 }