DSP

全局音效管理器

2019-07-13 11:10发布

近期经常用到全局音效的管理问题,就直接写了一个管理器,因为是在小游戏里面使用,暂时只用到了这些功能,后面有机会以在继续补充··· 关于音效的动态加载,因为实际项目中并未用到(小游戏,采用序列化的方式),这里临时用Resources加载··· 话不多说,都在注释里 using UnityEngine; using System.Collections; using System.Collections.Generic; public class AudioMgr : MonoBehaviour { //序列化 [Header("背景音乐")] [SerializeField] AudioClip backgroundMusic; [Header("音效")] [SerializeField] AudioClip[] audioClips; [Header("Resources加载路径")] [SerializeField] string clipResourcePath = "AudioClip"; [Header("保留空闲播放器的数量")] [SerializeField] int emptySourceCount = 3; //播放器 AudioSource baseSource; AudioSource bgmSource; //播放器list,音效Dictionary List audioSourceList = new List(); Dictionary audioClipDic = new Dictionary(); bool soundEnable; bool bgmEnable; string soundPlayerPrefsName = "soundPlayerPrefsName"; string bgmPlayerPrefsName = "bgmPlayerPrefsName"; //将该脚本挂载到场景GameObject,通过单例调用 public static AudioMgr Instance; void Awake() { Instance = this; } void Start() { Init(); } /* //若不需要序列化,音效采用动态加载的方式,可以不挂载该脚本,自动生成 static AudioMgr instance; public static AudioMgr Instance { get { if(instance == null) { instance = new GameObject("AudioMgr").AddComponent(); instance.Init(); } return instance; } } */ public void Update() { if (Input.GetKeyDown(KeyCode.Alpha1)) DestroyEmptySource(); if (Input.GetKeyDown(KeyCode.Alpha2)) PlaySound("2"); if (Input.GetKeyDown(KeyCode.Alpha3)) PlaySound("3"); if (Input.GetKeyDown(KeyCode.Alpha4)) SoundAudioEnable = !SoundAudioEnable; if (Input.GetKeyDown(KeyCode.Alpha5)) BgmAudioEnable = !BgmAudioEnable; } public void Init() { //生成base播放器 baseSource = new GameObject("BaseAudioSource").AddComponent(); baseSource.transform.parent = AudioMgr.Instance.transform; baseSource.playOnAwake = true; baseSource.loop = false; //BGM播放器 bgmSource = Instantiate(baseSource, transform); bgmSource.gameObject.name = "BackgroundSource"; bgmSource.loop = true; if (backgroundMusic != null) bgmSource.clip = backgroundMusic; ResetAudio(); } //读取并还原开关设置状态 void ResetAudio() { soundEnable = (PlayerPrefs.GetInt(soundPlayerPrefsName, 1) > 0) ? true : false; ; bgmEnable = (PlayerPrefs.GetInt(bgmPlayerPrefsName, 1) > 0) ? true : false; ; if (bgmEnable) bgmSource.Play(); } //设置、获取 音效、背景音乐开关状态 public bool SoundAudioEnable { get { return soundEnable; } set { if (soundEnable != value) { soundEnable = value; PlayerPrefs.SetInt(soundPlayerPrefsName, soundEnable ? 1 : 0); } } } public bool BgmAudioEnable { get { return bgmEnable; } set { if(bgmEnable != value) { bgmEnable = value; PlayerPrefs.SetInt(bgmPlayerPrefsName, bgmEnable ? 1 : 0); if(bgmEnable) bgmSource.Play(); else bgmSource.Stop(); } } } //播放音效(音效/名字) public void PlaySound(string clipName) { PlaySound(GetClipByName(clipName)); } public void PlaySound(AudioClip clip) { if (soundEnable && clip!= null) StartCoroutine(PlayAndDisableSource(clip)); } //设置背景音乐(音效/名字) public void SetBGMClip(string bgmName) { SetBGMClip(GetClipByName(bgmName)); } public void SetBGMClip(AudioClip bgmClip) { if (bgmClip != null) { bgmSource.clip = bgmClip; BgmAudioEnable = true; } } //销毁多余空闲播放器,保留指定数量备用 //可在指定条件下触发,或者利用定时器间隔固定时间进行清理 public void DestroyEmptySource() { if (audioSourceList.Count > emptySourceCount) { for (int i = audioSourceList.Count - 1; i >= emptySourceCount; i--) { if (audioSourceList[i].enabled) return; else { Destroy(audioSourceList[i].gameObject); audioSourceList.RemoveAt(i); } } } } // -------------- //播放一段音效,并在播放完成后,回收播放器 IEnumerator PlayAndDisableSource(AudioClip clip) { AudioSource audioSource = GetOneEmptySource(); audioSource.clip = clip; audioSource.Play(); while (audioSource.isPlaying) { yield return new WaitForEndOfFrame(); } audioSource.enabled = false; } //获取一个空的播放器 AudioSource GetOneEmptySource() { //遍历是否有空闲播放器 for (int i = 0; i < audioSourceList.Count; i++) { if (!audioSourceList[i].enabled) { audioSourceList[i].enabled = true; return audioSourceList[i]; } } //若没有,创建新的,并添加到list中统一管理 AudioSource tmpGo = Instantiate(baseSource, transform); audioSourceList.Add(tmpGo); return tmpGo; } //通过名字获取音效片段 AudioClip GetClipByName(string clipName) { //获取过的音效,将存在字典中,下次直接通过字典获取 if (audioClipDic.ContainsKey(clipName)) { return audioClipDic[clipName]; } else { //面板序列化 if(audioClips != null) { for (int i = 0; i < audioClips.Length; i++) { if (clipName == audioClips[i].name) { audioClipDic.Add(audioClips[i].name, audioClips[i]); return audioClips[i]; } } } Debug.Log(" 未序列化该音效 " + clipName); //Resources加载 if (!string.IsNullOrEmpty(clipResourcePath)) { AudioClip tmpNewAudioClip; tmpNewAudioClip = Resources.Load(clipResourcePath + "/" + clipName); if (tmpNewAudioClip != null) { audioClipDic.Add(clipName, tmpNewAudioClip); return tmpNewAudioClip; } else Debug.Log(" Resources加载失败 " + clipName); } else Debug.Log(" Resources路径为空 " + clipName); return null; } } } 若有任何意见或建议,欢迎分享讨论~~~