摄像机区域的架构改动
This commit is contained in:
115
Assets/_Game/Scripts/Audio/BGMController.cs
Normal file
115
Assets/_Game/Scripts/Audio/BGMController.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using BaseGames.Core;
|
||||
using BaseGames.Core.Events;
|
||||
|
||||
namespace BaseGames.Audio
|
||||
{
|
||||
/// <summary>BGM 状态机内部状态。</summary>
|
||||
public enum MusicState
|
||||
{
|
||||
Exploration, // 默认:区域探索 BGM
|
||||
Boss, // Boss 战:Boss 主题 BGM
|
||||
Victory, // Boss 击败后短暂胜利音乐
|
||||
None, // 过场/死亡/主菜单时由 BGMController 直接切换
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BGM 控制器:订阅世界/Boss/游戏状态事件,指挥 AudioManager 切换 BGM 和快照。
|
||||
/// 挂在 Persistent 场景 [AudioManager] 子对象上。
|
||||
/// </summary>
|
||||
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 readonly CompositeDisposable _subscriptions = new();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Debug.Assert(_config != null, "[BGMController] _config 未赋值,请在 Inspector 中指定 AudioConfigSO。", this);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_onBossFightToggled?.Subscribe(OnBossFightToggled).AddTo(_subscriptions);
|
||||
_onRegionEntered?.Subscribe(OnRegionEntered).AddTo(_subscriptions);
|
||||
_onGameStateChanged?.Subscribe(HandleStateChanged).AddTo(_subscriptions);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
_subscriptions.Clear();
|
||||
}
|
||||
|
||||
private void OnBossFightToggled(bool started)
|
||||
{
|
||||
if (started)
|
||||
{
|
||||
_musicState = MusicState.Boss;
|
||||
var clip = _config.GetBossBGM(_currentRegion);
|
||||
if (clip == null)
|
||||
{
|
||||
Debug.LogWarning($"[BGMController] 区域 '{_currentRegion}' 未配置 Boss BGM,将保持当前音乐。", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
_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.VictoryStingBGM,
|
||||
fadeOutDur: 0.3f, fadeInDur: 0.1f);
|
||||
float dur = _config.VictoryStingDuration;
|
||||
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.GetZoneBGM(regionId);
|
||||
if (clip == null)
|
||||
{
|
||||
Debug.LogWarning($"[BGMController] 区域 '{regionId}' 未配置 BGM,将保持当前音乐。", this);
|
||||
return;
|
||||
}
|
||||
_audioManager.PlayBGM(clip, fadeOutDur: 1f, fadeInDur: 1f);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleStateChanged(GameStateId state)
|
||||
{
|
||||
if (state == GameStates.MainMenu)
|
||||
_audioManager.PlayBGM(_config.MainMenuBGM,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user