Unity的音頻管理器
public class MusicManager : MonoBehaviour
{
#region 單例
private static MusicManager instance = null;
public static MusicManager Instance
{
get
{
GameObject musicMgr = GameObject.Find("MusicManager");
if (musicMgr == null)
{
musicMgr = new GameObject("MusicManager");
}
if (instance == null)
{
instance = musicMgr.GetComponent<MusicManager>();
if (instance == null)
{
instance = musicMgr.AddComponent<MusicManager>();
}
}
return instance;
}
}
#endregion
private AudioSource musicAudioSource;//背景音樂的AudioSource
private List<AudioSource> unusedSoundAudioSourceList; // 存放可以使用的音頻元件
private List<AudioSource> usedSoundAudioSourceList; // 存放正在使用的音頻元件
private Dictionary<string, AudioClip> audioClipDict; // 緩存音頻檔案
private float musicVolume = 1; //背景音樂聲音
private float soundVolume = 1; //音效聲音
public string musicVolumePrefs = "MusicVolume";//本地緩存背景音樂的鍵
public string soundVolumePrefs = "SoundVolume";//本地緩存音效的鍵
private int poolCount = 5; // AudioSource對象池數量
void Awake()
{
//初始化
musicAudioSource = gameObject.AddComponent<AudioSource>();
unusedSoundAudioSourceList = new List<AudioSource>();
usedSoundAudioSourceList = new List<AudioSource>();
audioClipDict = new Dictionary<string, AudioClip>();
DontDestroyOnLoad(this.gameObject);
}
void Start() { }
public void Init()
{
// 從本地緩存讀取聲音音量
if (PlayerPrefs.HasKey(musicVolumePrefs))
{
musicVolume = PlayerPrefs.GetFloat(musicVolumePrefs,1);
}
if (PlayerPrefs.HasKey(soundVolumePrefs))
{
soundVolume = PlayerPrefs.GetFloat(soundVolumePrefs,1);
}
}
/// <summary>
/// 播放背景音樂
/// </summary>
/// <param name="path">路徑</param>
/// <param name="isLoop">是否循環</param>
public void PlayMusic(string path, bool isLoop = true)
{
//TODO背景音樂的淡入淡出用DOTWEEN
musicAudioSource.clip = GetAudioClip(path);
musicAudioSource.clip.LoadAudioData();
musicAudioSource.loop = isLoop;
musicAudioSource.volume = musicVolume;
musicAudioSource.Play();
}
/// <summary>
/// 播放音效
/// </summary>
/// <param name="path">音效路徑</param>
/// <param name="func">回調</param>
public void PlaySound(string path, LuaFunction func)
{
AudioSource audioSource = null;
if (unusedSoundAudioSourceList.Count != 0)
{
audioSource = UnusedToUsed();
}
else
{
AddAudioSource();
audioSource = UnusedToUsed();
}
audioSource.clip = GetAudioClip(path);
audioSource.clip.LoadAudioData();
audioSource.volume = soundVolume;
audioSource.loop = false;
audioSource.Play();
StartCoroutine(WaitPlayEnd(audioSource, func));
}
/// <summary>
/// 播放3d音效
/// </summary>
/// <param name="path"></param>
/// <param name="position"></param>
public void Play3dSound(string path, Vector3 position)
{
AudioClip ac = GetAudioClip(path);
AudioSource.PlayClipAtPoint(ac, position);
}
/// <summary>
/// 設定音量
/// </summary>
/// <param name="music">背景音樂的音量</param>
/// <param name="sound">音效的音量</param>
public void SetVolume(float music,float sound)
{
ChangeMusicVolume(music);
ChangeSoundVolume(sound);
}
/// <summary>
/// 擷取音頻檔案,擷取後會緩存一份
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private AudioClip GetAudioClip(string path)
{
if (audioClipDict.ContainsKey(path) == false)
{
AudioClip ac = Resources.Load(path) as AudioClip;
if (ac == null)
{
Debug.LogError("音頻在Resource中不存在,請檢查音頻資源--path" + path);
return null;
}
audioClipDict.Add(path, ac);
}
return audioClipDict[path];
}
/// <summary>
/// 添加音頻元件
/// </summary>
/// <returns></returns>
private AudioSource AddAudioSource()
{
if (unusedSoundAudioSourceList.Count != 0)
{
return UnusedToUsed();
}
else
{
AudioSource audioSource = gameObject.AddComponent<AudioSource>();
unusedSoundAudioSourceList.Add(audioSource);
return audioSource;
}
}
/// <summary>
/// 将未使用的音頻元件移至已使用集合裡
/// </summary>
/// <returns></returns>
private AudioSource UnusedToUsed()
{
AudioSource audioSource = unusedSoundAudioSourceList[0];
unusedSoundAudioSourceList.RemoveAt(0);
usedSoundAudioSourceList.Add(audioSource);
return audioSource;
}
/// <summary>
/// 當播放音效結束後,将其移至未使用集合
/// </summary>
/// <param name="audioSource"></param>
/// <returns></returns>
IEnumerator WaitPlayEnd(AudioSource audioSource, LuaFunction func)
{
yield return new WaitUntil(() => { return !audioSource.isPlaying; });
UsedToUnused(audioSource);
if (func != null)
{
func.Call();
func.Dispose();
func = null;
}
}
/// <summary>
/// 将使用完的音頻元件移至未使用集合裡
/// </summary>
/// <param name="audioSource"></param>
private void UsedToUnused(AudioSource audioSource)
{
if (usedSoundAudioSourceList.Contains(audioSource))
{
usedSoundAudioSourceList.Remove(audioSource);
}
if (unusedSoundAudioSourceList.Count >= poolCount)
{
Destroy(audioSource);
}
else if (audioSource != null && !unusedSoundAudioSourceList.Contains(audioSource))
{
unusedSoundAudioSourceList.Add(audioSource);
}
}
/// <summary>
/// 修改背景音樂音量
/// </summary>
/// <param name="volume"></param>
private void ChangeMusicVolume(float volume)
{
musicVolume = volume;
musicAudioSource.volume = volume;
PlayerPrefs.SetFloat(musicVolumePrefs, volume);
}
/// <summary>
/// 修改音效音量
/// </summary>
/// <param name="volume"></param>
private void ChangeSoundVolume(float volume)
{
soundVolume = volume;
for (int i = 0; i < unusedSoundAudioSourceList.Count; i++)
{
unusedSoundAudioSourceList[i].volume = volume;
}
for (int i = 0; i < usedSoundAudioSourceList.Count; i++)
{
usedSoundAudioSourceList[i].volume = volume;
}
PlayerPrefs.SetFloat(soundVolumePrefs, volume);
}