/******************************************************************** 文件: AudioMgr.cs 作者: 梦语 邮箱: 1982614048@qq.com 创建时间: 2024/03/29 17:28:19 最后修改: 梦语 最后修改时间: 2024/04/03 17:09:26 功能: *********************************************************************/ using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Ether { public class AudioManager : SingletonAutoMono { private AudioSource backGroundSource; //背景音乐Source private List allEffectSource = new List(); //所有播放音效Source private Dictionary clipCache = new Dictionary(); //clip缓存 private int releaseCount = 3; //空闲source大于这个数量时释放 /// /// 全局音量 /// [SerializeField, SetProperty("GlobalVolume"), Range(0f, 1f)] private float globalVolume = 1f; public float GlobalVolume { get => globalVolume; set { globalVolume = value; RefreshGlobalVolume(); } } /// /// 背景音量 /// [SerializeField, SetProperty("BackGroundVolume"), Range(0f, 1f)] private float backGroundVolume = 1f; public float BackGroundVolume { get => backGroundVolume; set { backGroundVolume = value; RefreshBackGroundVolume(); } } /// /// 音效音量 /// [SerializeField, SetProperty("EffectVolume"), Range(0f, 1f)] private float effectVolume = 1f; public float EffectVolume { get => effectVolume; set { effectVolume = value; RefreshEffectVolume(); } } /// /// 是否静音 /// [SerializeField, SetProperty("IsMute")] private bool isMute = false; public bool IsMute { get => isMute; set { isMute = value; RefreshGlobalVolume(); } } /// /// 刷新全局音量 /// private void RefreshGlobalVolume() { RefreshBackGroundVolume(); RefreshEffectVolume(); } /// /// 刷新背景音量 /// private void RefreshBackGroundVolume() { backGroundSource.volume = globalVolume * backGroundVolume; backGroundSource.mute = isMute; } /// /// 刷新音效音量 /// private void RefreshEffectVolume() { foreach (var source in allEffectSource) { source.volume = globalVolume * effectVolume; source.mute = isMute; } } /// /// 播放背景音乐 /// public void PlayBgAudio(string name) { AudioClip clip = GetAudioClip($"Audio/{name}"); RefreshBackGroundVolume(); Play(backGroundSource, clip, true); } public bool IsPlayingBgAudio() { return backGroundSource.isPlaying; } /// /// 停止背景音乐 /// public void StopBgAudio() { backGroundSource?.Stop(); } /// /// 播放 /// private void Play(AudioSource source, AudioClip clip, bool isLoop = false) { source.clip = clip; source.loop = isLoop; source.mute = isMute; source.Play(); } /// /// 播放音效 /// public void PlayEffectAudio(string name, bool isLoop = false) { AudioClip clip = GetAudioClip($"Audio/{name}"); if (clip == null) { return; } AudioSource tmpSouce = GetFreeEffectSource(); RefreshEffectVolume(); Play(tmpSouce, clip, isLoop); } /// /// 停止音效 /// /// public void StopEffectAudio(string name) { foreach (var source in allEffectSource) { if (source.clip.name == name && source.isPlaying) { source.Stop(); } } } /// /// 停止所有音效 /// public void StopAllEffectAudio() { foreach (var source in allEffectSource) { source.Stop(); } } /// /// 是否正在播放某个音效 /// /// /// public bool IsPlayingEffectAudio(string name) { foreach (var source in allEffectSource) { if (source.clip.name == name && source.isPlaying) { return true; } } return false; } /// /// 根据名字获取clip /// private AudioClip GetAudioClip(string name) { if (clipCache.ContainsKey(name)) { return clipCache[name]; } AudioClip clip = LoaderTools.LoadAsset(name); if (clip != null) { clipCache.Add(name, clip); } return clip; } /// /// 获取一个空闲的AudioSource /// /// private AudioSource GetFreeEffectSource() { foreach (var souce in allEffectSource) { if (!souce.isPlaying) { ReleaseSurplus(); return souce; } } AudioSource tmpSouce = gameObject.AddComponent(); allEffectSource.Add(tmpSouce); return tmpSouce; } /// /// 释放空闲的AudioSource /// private void ReleaseSurplus() { int freeCount = 0; List remove = new List(); foreach (var source in allEffectSource) { if (!source.isPlaying) { freeCount++; if (freeCount > releaseCount) { remove.Add(source); } } } foreach (var source in remove) { allEffectSource.Remove(source); Destroy(source); } remove.Clear(); } public override void Init() { Clear(); if (backGroundSource == null) { backGroundSource = gameObject.AddComponent(); } RefreshGlobalVolume(); } public override void Clear() { allEffectSource.Clear(); clipCache.Clear(); } } }