using UnityEngine; using BaseGames.Core.Events; using BaseGames.Combat; namespace BaseGames.Audio { /// /// 订阅战斗/死亡事件,通过 AudioManager 播放对应 SFX。 /// 挂载在 Persistent 场景的 [Systems] GameObject 上。 /// public class CombatSFXController : MonoBehaviour { [Header("Event Channels")] [SerializeField] private HitConfirmedEventChannelSO _onHitConfirmed; [SerializeField] private VoidEventChannelSO _onPlayerDied; [Header("Default Hit SFX")] [SerializeField] private AudioClip _defaultHitSFX; [Header("Per-Type Hit SFX (optional, overrides default)")] [SerializeField] private AudioClip _sparkHitSFX; [SerializeField] private AudioClip _slashHitSFX; [SerializeField] private AudioClip _bloodHitSFX; [SerializeField] private AudioClip _magicHitSFX; [SerializeField] private AudioClip _heavyHitSFX; [SerializeField] private AudioClip _critHitSFX; [SerializeField] private AudioClip _parryHitSFX; [SerializeField] private AudioClip _fireHitSFX; [SerializeField] private AudioClip _iceHitSFX; [Header("Death SFX")] [SerializeField] private AudioClip _playerDeathSFX; private void OnEnable() { if (_onHitConfirmed != null) _onHitConfirmed.OnEventRaised += HandleHit; if (_onPlayerDied != null) _onPlayerDied.OnEventRaised += HandlePlayerDied; } private void OnDisable() { if (_onHitConfirmed != null) _onHitConfirmed.OnEventRaised -= HandleHit; if (_onPlayerDied != null) _onPlayerDied.OnEventRaised -= HandlePlayerDied; } private void HandleHit(HitInfo info) { AudioClip clip = ResolveHitClip(info.DamageInfo.FxType); if (clip == null) return; AudioManager.Instance.PlaySFXAtPosition(clip, info.HitPoint); } private void HandlePlayerDied() { if (_playerDeathSFX == null) return; AudioManager.Instance.PlaySFX(_playerDeathSFX); } private AudioClip ResolveHitClip(HitFxType fxType) { AudioClip perType = fxType switch { HitFxType.Spark => _sparkHitSFX, HitFxType.Slash => _slashHitSFX, HitFxType.Blood => _bloodHitSFX, HitFxType.Magic => _magicHitSFX, HitFxType.Heavy => _heavyHitSFX, HitFxType.Crit => _critHitSFX, HitFxType.Parry => _parryHitSFX, HitFxType.Fire => _fireHitSFX, HitFxType.Ice => _iceHitSFX, _ => null }; return perType != null ? perType : _defaultHitSFX; } } }