using UnityEngine; /// /// 统一音频管理器——挂在 [Managers] 上,管理所有背景音乐/音效/语音。 /// public class AudioManager : MonoBehaviour { public static AudioManager I { get; private set; } [Header("背景音乐")] [SerializeField] private AudioClip _homeBg; [SerializeField] private AudioClip _experimentBg; [Range(0,1)] public float BgVolume = 0.5f; [Header("音效")] [SerializeField] private AudioClip _basketballSfx; [SerializeField] private AudioClip _manCallSfx; private AudioSource _bgSource; private AudioSource _sfxSource; private AudioSource _voiceSource; void Awake() { I = this; _bgSource = gameObject.AddComponent(); _bgSource.loop = true; _bgSource.playOnAwake = false; _bgSource.spatialBlend = 0f; _sfxSource = gameObject.AddComponent(); _sfxSource.playOnAwake = false; _sfxSource.spatialBlend = 0f; _voiceSource = gameObject.AddComponent(); _voiceSource.playOnAwake = false; _voiceSource.spatialBlend = 0f; #if UNITY_EDITOR if (_homeBg == null) _homeBg = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Audio/homeBackgroundMusic.mp3"); if (_experimentBg == null) _experimentBg = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Audio/backgroundMusic.mp3"); if (_basketballSfx == null) _basketballSfx = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Audio/start/basketballSound.wav"); if (_manCallSfx == null) _manCallSfx = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Audio/start/mancall.wav"); #endif Debug.Log($"[AudioManager] 就绪 homeBg={_homeBg!=null} expBg={_experimentBg!=null} sfx={_basketballSfx!=null}/{_manCallSfx!=null}"); } // ────── 背景音乐 ────── public void PlayHomeBg() { if (_homeBg == null) return; _bgSource.clip = _homeBg; _bgSource.volume = BgVolume; _bgSource.Play(); Debug.Log($"[AudioManager] 首页bg isPlaying={_bgSource.isPlaying}"); } public void PlayExperimentBg() { if (_experimentBg == null) return; _bgSource.clip = _experimentBg; _bgSource.volume = BgVolume; _bgSource.Play(); Debug.Log($"[AudioManager] 实验bg isPlaying={_bgSource.isPlaying}"); } public void StopBgMusic() { _bgSource.Stop(); Debug.Log("[AudioManager] 停止bg"); } // ────── 音效(可打断) ────── public void PlaySfx(AudioClip clip) { if (clip == null) return; _sfxSource.Stop(); _sfxSource.clip = clip; _sfxSource.Play(); } public void StopSfx() { _sfxSource.Stop(); } public void PlayBasketballSfx() => PlaySfx(_basketballSfx); public void PlayManCallSfx() => PlaySfx(_manCallSfx); // ────── 语音(可打断) ────── public void PlayVoice(AudioClip clip) { if (clip == null) return; _voiceSource.Stop(); _voiceSource.clip = clip; _voiceSource.Play(); Debug.Log($"[AudioManager] 播放语音: {clip.name}"); } public void StopVoice() { _voiceSource.Stop(); } public void SwitchToCamera3Smooth() { StartCoroutine(Camera3SwitchRoutine()); } System.Collections.IEnumerator Camera3SwitchRoutine() { var black = GameObject.Find("BlackScreenPanel"); var blackImg = black != null ? black.GetComponent() : null; float duration = 0.8f; // 渐入黑 if (black != null && blackImg != null) { black.SetActive(true); for (float t = 0f; t < duration; t += Time.deltaTime) { blackImg.color = new Color(0, 0, 0, t / duration); yield return null; } blackImg.color = Color.black; } // 切换摄像机 var cam2 = GameObject.Find("camera2"); var cam3 = GameObject.Find("camera3"); if (cam2 != null) { var c = cam2.GetComponent(); if (c != null) c.enabled = false; } if (cam3 != null) { var c = cam3.GetComponent(); if (c != null) c.enabled = true; } Debug.Log("[AudioManager] camera2→camera3 平滑切换完成"); yield return new WaitForSeconds(0.2f); // 渐出黑 if (black != null && blackImg != null) { for (float t = 0f; t < duration; t += Time.deltaTime) { blackImg.color = new Color(0, 0, 0, 1f - t / duration); yield return null; } blackImg.color = new Color(0, 0, 0, 0); black.SetActive(false); } } }