using UnityEngine; using BaseGames.Core.Events; using BaseGames.Combat; namespace BaseGames.Audio { /// /// 订阅战斗/死亡事件,通过 GlobalSFXPlayer 播放对应 AudioEventSO 音效。 /// 挂载在 Persistent 场景的 [Systems] GameObject 上。 /// 使用 AudioEventSO 替代裸 AudioClip,支持随机音量 / 音调 / 多片段。 /// public class CombatSFXController : MonoBehaviour { [Header("Event Channels")] [SerializeField] private HitConfirmedEventChannelSO _onHitConfirmed; [SerializeField] private VoidEventChannelSO _onPlayerDied; [Header("Default Hit SFX")] [SerializeField] private AudioEventSO _defaultHitSFX; [Header("Per-Type Hit SFX (optional, overrides default)")] [SerializeField] private AudioEventSO _sparkHitSFX; [SerializeField] private AudioEventSO _slashHitSFX; [SerializeField] private AudioEventSO _bloodHitSFX; [SerializeField] private AudioEventSO _magicHitSFX; [SerializeField] private AudioEventSO _heavyHitSFX; [SerializeField] private AudioEventSO _critHitSFX; [SerializeField] private AudioEventSO _parryHitSFX; [SerializeField] private AudioEventSO _fireHitSFX; [SerializeField] private AudioEventSO _iceHitSFX; [Header("Death SFX")] [SerializeField] private AudioEventSO _playerDeathSFX; private readonly CompositeDisposable _subs = new(); private void OnEnable() { _onHitConfirmed?.Subscribe(HandleHit).AddTo(_subs); _onPlayerDied?.Subscribe(HandlePlayerDied).AddTo(_subs); } private void OnDisable() { _subs.Clear(); } private void HandleHit(HitInfo info) { AudioEventSO sfx = ResolveHitSFX(info.DamageInfo.FxType); if (sfx == null) return; GlobalSFXPlayer.Play(sfx, info.HitPoint); } private void HandlePlayerDied() { if (_playerDeathSFX == null) return; GlobalSFXPlayer.Play(_playerDeathSFX); } private AudioEventSO ResolveHitSFX(HitFxType fxType) { AudioEventSO 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; } } }