feat: 音频系统统一重写—AudioManager管理全部音频
新增 AudioManager.cs 挂在 [Managers] 上: - _bgSource: 背景音乐(首页/实验), spatialBlend=0, BgVolume可调 - _sfxSource: 音效(篮球/manCall), Stop()可打断 - _voiceSource: 语音中断播放 替换: - PageController: BGMController→AudioManager.I - OpeningFlowController: PlayClipAtPoint→AudioManager.I.PlayBasketball/ManCallSfx - 删除 BGMController.cs - 删除旧 AudioManager.cs(Assets/Scripts/Audio/旧版)
This commit is contained in:
@@ -127,7 +127,7 @@ public class OpeningFlowController : MonoBehaviour
|
||||
|
||||
// Step 2: Shoot + 篮球音效
|
||||
Debug.Log("[OpeningFlow] Step2: Shoot 开始");
|
||||
if (_basketballClip != null) AudioSource.PlayClipAtPoint(_basketballClip, transform.position);
|
||||
if (AudioManager.I != null) AudioManager.I.PlayBasketballSfx();
|
||||
if (_manAnimator != null) { _manAnimator.Play("Shoot", 0, 0f); Debug.Log("[OpeningFlow] Shoot Play 已触发"); }
|
||||
yield return new WaitForSeconds(3.15f);
|
||||
Debug.Log("[OpeningFlow] Step2: Shoot 结束");
|
||||
@@ -136,7 +136,7 @@ public class OpeningFlowController : MonoBehaviour
|
||||
Debug.Log("[OpeningFlow] Step3: manfull 开始");
|
||||
if (_manAnimator != null) { _manAnimator.Play("manfull", 0, 0f); }
|
||||
yield return new WaitForSeconds(2.1f);
|
||||
if (_manCallClip != null) AudioSource.PlayClipAtPoint(_manCallClip, transform.position);
|
||||
if (AudioManager.I != null) AudioManager.I.PlayManCallSfx();
|
||||
Debug.Log("[OpeningFlow] manfull 播放完成, 停留 2s");
|
||||
yield return new WaitForSeconds(2f);
|
||||
|
||||
|
||||
@@ -1,92 +1,98 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 音频管理器:管理背景音乐和步骤语音解说。
|
||||
/// 挂在场景 GameObject 上,通过 AudioSource 组件播放。
|
||||
/// 统一音频管理器——挂在 [Managers] 上,管理所有背景音乐/音效/语音。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(AudioSource))]
|
||||
public class AudioManager : MonoBehaviour
|
||||
{
|
||||
public static AudioManager Instance { get; private set; }
|
||||
|
||||
[Header("音频源")]
|
||||
[SerializeField] private AudioSource _bgmSource;
|
||||
[SerializeField] private AudioSource _voiceSource;
|
||||
public static AudioManager I { get; private set; }
|
||||
|
||||
[Header("背景音乐")]
|
||||
public AudioClip BGMClip;
|
||||
[Range(0f, 1f)] public float BGMVolume = 0.3f;
|
||||
[SerializeField] private AudioClip _homeBg;
|
||||
[SerializeField] private AudioClip _experimentBg;
|
||||
[Range(0,1)] public float BgVolume = 0.5f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null) { Destroy(gameObject); return; }
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
[Header("音效")]
|
||||
[SerializeField] private AudioClip _basketballSfx;
|
||||
[SerializeField] private AudioClip _manCallSfx;
|
||||
|
||||
if (_bgmSource == null) _bgmSource = GetComponent<AudioSource>();
|
||||
if (_voiceSource == null)
|
||||
private AudioSource _bgSource;
|
||||
private AudioSource _sfxSource;
|
||||
private AudioSource _voiceSource;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
I = this;
|
||||
_bgSource = gameObject.AddComponent<AudioSource>();
|
||||
_bgSource.loop = true;
|
||||
_bgSource.playOnAwake = false;
|
||||
_bgSource.spatialBlend = 0f;
|
||||
|
||||
_sfxSource = gameObject.AddComponent<AudioSource>();
|
||||
_sfxSource.playOnAwake = false;
|
||||
_sfxSource.spatialBlend = 0f;
|
||||
|
||||
_voiceSource = gameObject.AddComponent<AudioSource>();
|
||||
_voiceSource.playOnAwake = false;
|
||||
_voiceSource.loop = false;
|
||||
}
|
||||
_voiceSource.spatialBlend = 0f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (_homeBg == null) _homeBg = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/homeBackgroundMusic.mp3");
|
||||
if (_experimentBg == null) _experimentBg = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/backgroundMusic.mp3");
|
||||
if (_basketballSfx == null) _basketballSfx = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/start/basketballSound.wav");
|
||||
if (_manCallSfx == null) _manCallSfx = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/start/mancall.wav");
|
||||
#endif
|
||||
Debug.Log($"[AudioManager] 就绪 homeBg={_homeBg!=null} expBg={_experimentBg!=null} sfx={_basketballSfx!=null}/{_manCallSfx!=null}");
|
||||
}
|
||||
|
||||
private void Start()
|
||||
// ────── 背景音乐 ──────
|
||||
public void PlayHomeBg()
|
||||
{
|
||||
PlayBGM();
|
||||
if (_homeBg == null) return;
|
||||
_bgSource.clip = _homeBg;
|
||||
_bgSource.volume = BgVolume;
|
||||
_bgSource.Play();
|
||||
Debug.Log($"[AudioManager] 首页bg isPlaying={_bgSource.isPlaying}");
|
||||
}
|
||||
|
||||
public void PlayBGM()
|
||||
public void PlayExperimentBg()
|
||||
{
|
||||
if (_bgmSource == null || BGMClip == null) return;
|
||||
_bgmSource.clip = BGMClip;
|
||||
_bgmSource.volume = BGMVolume;
|
||||
_bgmSource.loop = true;
|
||||
_bgmSource.Play();
|
||||
if (_experimentBg == null) return;
|
||||
_bgSource.clip = _experimentBg;
|
||||
_bgSource.volume = BgVolume;
|
||||
_bgSource.Play();
|
||||
Debug.Log($"[AudioManager] 实验bg isPlaying={_bgSource.isPlaying}");
|
||||
}
|
||||
|
||||
public void StopBGM()
|
||||
public void StopBgMusic()
|
||||
{
|
||||
if (_bgmSource != null) _bgmSource.Stop();
|
||||
_bgSource.Stop();
|
||||
Debug.Log("[AudioManager] 停止bg");
|
||||
}
|
||||
|
||||
/// <summary>播放一步语音解说,自动打断前一条</summary>
|
||||
public void PlayVoice(AudioClip clip, float volume = 1f)
|
||||
// ────── 音效(可打断) ──────
|
||||
public void PlaySfx(AudioClip clip)
|
||||
{
|
||||
if (_voiceSource == null || clip == null) return;
|
||||
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.volume = volume;
|
||||
_voiceSource.Play();
|
||||
Debug.Log($"[AudioManager] 播放语音: {clip.name}");
|
||||
}
|
||||
|
||||
/// <summary>停止语音</summary>
|
||||
public void StopVoice()
|
||||
{
|
||||
if (_voiceSource != null) _voiceSource.Stop();
|
||||
}
|
||||
|
||||
/// <summary>按文件名从 StreamingAssets 加载并播放语音</summary>
|
||||
public void PlayVoiceFromFile(string fileName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fileName)) return;
|
||||
StartCoroutine(LoadAndPlayVoice(fileName));
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator LoadAndPlayVoice(string fileName)
|
||||
{
|
||||
string path = System.IO.Path.Combine(Application.streamingAssetsPath, "Voice", fileName);
|
||||
using var www = UnityEngine.Networking.UnityWebRequestMultimedia.GetAudioClip(path, AudioType.WAV);
|
||||
yield return www.SendWebRequest();
|
||||
if (www.result == UnityEngine.Networking.UnityWebRequest.Result.Success)
|
||||
{
|
||||
var clip = UnityEngine.Networking.DownloadHandlerAudioClip.GetContent(www);
|
||||
PlayVoice(clip);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"AudioManager: 加载语音失败 {path}");
|
||||
}
|
||||
}
|
||||
public void StopVoice() { _voiceSource.Stop(); }
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 背景音乐控制器——挂在 [Managers] 上,独立于 PageController。
|
||||
/// 静态方法供外部调用。
|
||||
/// </summary>
|
||||
public class BGMController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private AudioClip _homeBgClip;
|
||||
[SerializeField] private AudioClip _experimentBgClip;
|
||||
private AudioSource _bgSource;
|
||||
|
||||
private static BGMController _instance;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
_bgSource = gameObject.AddComponent<AudioSource>();
|
||||
_bgSource.loop = true;
|
||||
_bgSource.playOnAwake = false;
|
||||
_bgSource.spatialBlend = 0f;
|
||||
_bgSource.volume = 0.5f;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (_homeBgClip == null) _homeBgClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/homeBackgroundMusic.mp3");
|
||||
if (_experimentBgClip == null) _experimentBgClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/backgroundMusic.mp3");
|
||||
#endif
|
||||
Debug.Log($"[BGMController] 就绪 homeBg={(_homeBgClip!=null)} expBg={(_experimentBgClip!=null)}");
|
||||
}
|
||||
|
||||
public static void PlayHomeBg()
|
||||
{
|
||||
if (_instance == null || _instance._homeBgClip == null) { Debug.LogWarning("[BGMController] PlayHomeBg 失败"); return; }
|
||||
_instance._bgSource.clip = _instance._homeBgClip;
|
||||
_instance._bgSource.volume = 0.5f;
|
||||
_instance._bgSource.Play();
|
||||
Debug.Log($"[BGMController] 播放首页bg isPlaying={_instance._bgSource.isPlaying}");
|
||||
}
|
||||
|
||||
public static void PlayExperimentBg()
|
||||
{
|
||||
if (_instance == null || _instance._experimentBgClip == null) { Debug.LogWarning("[BGMController] PlayExperimentBg 失败"); return; }
|
||||
_instance._bgSource.clip = _instance._experimentBgClip;
|
||||
_instance._bgSource.volume = 0.5f;
|
||||
_instance._bgSource.Play();
|
||||
Debug.Log($"[BGMController] 播放实验bg isPlaying={_instance._bgSource.isPlaying}");
|
||||
}
|
||||
|
||||
public static void StopBgMusic()
|
||||
{
|
||||
if (_instance != null) _instance._bgSource.Stop();
|
||||
Debug.Log("[BGMController] 停止bg");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5a0e43c7217447f9b4be5e2434520e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -121,8 +121,8 @@ public class PageController : MonoBehaviour
|
||||
|
||||
if (_uiManager != null)
|
||||
_uiManager.enabled = (page == Page.Experiment);
|
||||
if (page == Page.Home) BGMController.PlayHomeBg(); // 背景音乐: 首页播 homeBg, 选固定方式时停, 实验启动时播 experimentBg
|
||||
if (page == Page.Home) BGMController.PlayHomeBg();
|
||||
if (page == Page.Home) AudioManager.I.PlayHomeBg(); // 背景音乐: 首页播 homeBg, 选固定方式时停, 实验启动时播 experimentBg
|
||||
if (page == Page.Home) AudioManager.I.PlayHomeBg();
|
||||
Debug.Log($"PageController(编辑器预览): 切换到 [{page}]");
|
||||
}
|
||||
#endif
|
||||
@@ -224,7 +224,7 @@ public class PageController : MonoBehaviour
|
||||
Debug.Log($"PageController: GameManager 已设置 Mode=[{gm.CurrentMode}] Fixation=[{gm.CurrentFixationMethod}]");
|
||||
|
||||
// 隐藏所有UI面板,准备播放片头动画
|
||||
BGMController.StopBgMusic();
|
||||
AudioManager.I.StopBgMusic();
|
||||
HideAllPages();
|
||||
|
||||
// 找到 OpeningFlowController 播放片头动画
|
||||
@@ -267,7 +267,7 @@ public class PageController : MonoBehaviour
|
||||
{
|
||||
Debug.Log("PageController: [ActivateExperimentObjects] 显示实验物件");
|
||||
|
||||
BGMController.PlayExperimentBg();
|
||||
AudioManager.I.PlayExperimentBg();
|
||||
|
||||
var allObjects = FindObjectsOfType<GameObject>(true);
|
||||
foreach (var go in allObjects)
|
||||
|
||||
Reference in New Issue
Block a user