chore: initial commit

This commit is contained in:
2026-05-08 11:04:00 +08:00
commit f55d2a57c3
6278 changed files with 866081 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
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 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);
}
}
}