using System.Collections; using UnityEngine; using BaseGames.Core; using BaseGames.Core.Events; namespace BaseGames.Audio { /// BGM 状态机内部状态。 public enum MusicState { Exploration, // 默认:区域探索 BGM Boss, // Boss 战:Boss 主题 BGM Victory, // Boss 击败后短暂胜利音乐 None, // 过场/死亡/主菜单时由 BGMController 直接切换 } /// /// BGM 控制器:订阅世界/Boss/游戏状态事件,指挥 AudioManager 切换 BGM 和快照。 /// 挂在 Persistent 场景 [AudioManager] 子对象上。 /// public class BGMController : MonoBehaviour { [SerializeField] private AudioManager _audioManager; [SerializeField] private AudioConfigSO _config; [Header("Event Channels - Subscribe")] [SerializeField] private GameStateEventChannelSO _onGameStateChanged; [SerializeField] private BoolEventChannelSO _onBossFightToggled; // true=开始, false=结束 [SerializeField] private StringEventChannelSO _onRegionEntered; private MusicState _musicState = MusicState.Exploration; private string _currentRegion = string.Empty; private void OnEnable() { if (_onBossFightToggled != null) _onBossFightToggled.OnEventRaised += OnBossFightToggled; if (_onRegionEntered != null) _onRegionEntered.OnEventRaised += OnRegionEntered; if (_onGameStateChanged != null) _onGameStateChanged.OnEventRaised += HandleStateChanged; } private void OnDisable() { if (_onBossFightToggled != null) _onBossFightToggled.OnEventRaised -= OnBossFightToggled; if (_onRegionEntered != null) _onRegionEntered.OnEventRaised -= OnRegionEntered; if (_onGameStateChanged != null) _onGameStateChanged.OnEventRaised -= HandleStateChanged; } private void OnBossFightToggled(bool started) { if (started) { _musicState = MusicState.Boss; var clip = _config != null ? _config.GetBossBGM(_currentRegion) : null; _audioManager.PlayBGM(clip, fadeOutDur: 1f, fadeInDur: 0.5f); _audioManager.TransitionToSnapshot("BossFight", 0.5f); } else { StartCoroutine(PlayVictoryThenRestore()); } } private IEnumerator PlayVictoryThenRestore() { _musicState = MusicState.Victory; _audioManager.PlayBGM(_config != null ? _config.VictoryStingBGM : null, fadeOutDur: 0.3f, fadeInDur: 0.1f); float dur = _config != null ? _config.VictoryStingDuration : 4f; yield return new WaitForSecondsRealtime(dur); _musicState = MusicState.Exploration; OnRegionEntered(_currentRegion); _audioManager.TransitionToSnapshot("Default", 1.0f); } private void OnRegionEntered(string regionId) { if (regionId == _currentRegion) return; _currentRegion = regionId; if (_musicState == MusicState.Exploration) { var clip = _config != null ? _config.GetZoneBGM(regionId) : null; _audioManager.PlayBGM(clip, fadeOutDur: 1f, fadeInDur: 1f); } } private void HandleStateChanged(GameStateId state) { // ⚠️ GameStateId 是 struct,不能用 switch;使用 if/else + GameStates 常量 if (state == GameStates.MainMenu) _audioManager.PlayBGM(_config != null ? _config.MainMenuBGM : null, fadeOutDur: 0.5f, fadeInDur: 1.0f); else if (state == GameStates.Paused) _audioManager.TransitionToSnapshot("Paused", 0.2f); else if (state == GameStates.Dead) _audioManager.TransitionToSnapshot("Dead", 1.5f); else if (state == GameStates.Gameplay) _audioManager.TransitionToSnapshot("Default", 0.3f); } } }