using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GameFramework
{
///
/// 音频片段数据,可挂到 ScriptableObject 或直接 SerializeField。
///
[System.Serializable]
public class AudioData
{
public AudioClip audioClip;
[Range(0f, 1f)] public float volume = 1f;
}
///
/// 全局音频管理器(持久单例)。
/// 管理 BGM(背景音乐,循环)和 SFX(音效,一次性)。
/// 音量通过 PlayerPrefs 持久化。
///
public class AudioManager : PersistentSingleton
{
const string PREF_BGM_VOLUME = "AudioManager_BGMVolume";
const string PREF_SFX_VOLUME = "AudioManager_SFXVolume";
AudioSource bgmPlayer; // 背景音乐播放器
AudioSource sfxPlayer; // 音效播放器
float bgmVolume = 1f;
float sfxVolume = 1f;
public float BGMVolume => bgmVolume;
public float SFXVolume => sfxVolume;
protected override void Awake()
{
base.Awake();
// 如果是重复实例,base.Awake 已调用 Destroy,这里直接返回
if (Instance != this) return;
// 创建两个 AudioSource
bgmPlayer = gameObject.AddComponent();
bgmPlayer.loop = true;
bgmPlayer.playOnAwake = false;
sfxPlayer = gameObject.AddComponent();
sfxPlayer.loop = false;
sfxPlayer.playOnAwake = false;
// 读取持久化音量
bgmVolume = PlayerPrefs.GetFloat(PREF_BGM_VOLUME, 1f);
sfxVolume = PlayerPrefs.GetFloat(PREF_SFX_VOLUME, 1f);
bgmPlayer.volume = bgmVolume;
sfxPlayer.volume = sfxVolume;
}
#region BGM
///
/// 播放背景音乐(循环)。
///
public void PlayBGM(AudioClip clip, bool restart = false)
{
if (clip == null) return;
if (bgmPlayer.isPlaying && bgmPlayer.clip == clip && !restart)
return;
bgmPlayer.clip = clip;
bgmPlayer.volume = bgmVolume;
bgmPlayer.Play();
}
public void StopBGM()
{
if (bgmPlayer.isPlaying)
bgmPlayer.Stop();
}
public void PauseBGM() => bgmPlayer.Pause();
public void UnpauseBGM() => bgmPlayer.UnPause();
public void SetBGMVolume(float volume)
{
bgmVolume = Mathf.Clamp01(volume);
bgmPlayer.volume = bgmVolume;
PlayerPrefs.SetFloat(PREF_BGM_VOLUME, bgmVolume);
PlayerPrefs.Save();
}
#endregion
#region SFX
///
/// 播放单个音效。
///
public void PlaySFX(AudioData data)
{
if (data == null || data.audioClip == null) return;
// sfxPlayer.volume 已在 Awake 中设为 sfxVolume,
// PlayOneShot 的 volumeScale 再乘以 data.volume,
// 最终音量 = sfxVolume * data.volume
sfxPlayer.PlayOneShot(data.audioClip, data.volume);
}
///
/// 从列表中随机播放一个音效。
///
public void PlayRandomSFX(AudioData data, List variants = null)
{
if (variants != null && variants.Count > 0)
{
PlaySFX(variants[Random.Range(0, variants.Count)]);
return;
}
PlaySFX(data);
}
public void SetSFXVolume(float volume)
{
sfxVolume = Mathf.Clamp01(volume);
PlayerPrefs.SetFloat(PREF_SFX_VOLUME, sfxVolume);
PlayerPrefs.Save();
}
#endregion
}
}