using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; /// /// 音效 音乐管理器 /// 2D声音全局 /// 管理音乐、音效播放 暂停、声音大小管理 /// public class MusicManager : BaseManager { private MusicManager() { musicObject = new GameObject("MusicObject"); GameObject.DontDestroyOnLoad(musicObject); musicObject.transform.position = Vector3.zero; MonoMgr.Instance.AddUpdateListener(Update); } /// /// 音乐音效组件挂在的对象 /// private readonly GameObject musicObject; /// /// 背景音乐播放组件 /// private AudioSource backMusicSource; /// /// 播放音效组件 /// private readonly List audioSources = new List(); /// /// 缓存池中的音效组件 /// private readonly List audioSourcesCache =new List(); /// /// 标记音效暂停 /// private bool isPauseSound = false; /// /// 播放背景音乐 /// /// b背景音乐资源文件名 Resources下路径名+文件名,不需要文件格式 /// 背景音乐声音大小 public void PlayBackMusic(string clipName,float volume) { ResourcesManager.Instance.LoadAsync(clipName, (clip) => { if (!clip) { Debug.Log("资源加载失败!请检查文件名"); } //背景音乐播放组件 唯一 if (backMusicSource == null) backMusicSource = musicObject.AddComponent(); backMusicSource.playOnAwake = false; //背景音乐声音 这个音乐根据项目 会有独立的设置数据 从设置数据传过来 backMusicSource.volume = volume; //背景音乐 文件 backMusicSource.clip = clip; //循环播放 backMusicSource.loop = true; //播放 backMusicSource.Play(); }); } /// /// 暂停背景音乐 /// public void PauseBackMusic() { if (backMusicSource == null) return; backMusicSource.Pause(); } /// /// 恢复播放 /// public void UnPauseBackMusic() { if (backMusicSource == null) return; backMusicSource.UnPause(); } /// /// 停止背景音乐 /// public void StopBackMusic() { if (backMusicSource == null) return; backMusicSource.Stop(); } /// /// 改变背景音乐声音大小 /// /// 声音值 public void ChangeBackMusic(float volume) { if (backMusicSource == null) return; backMusicSource.volume = volume; } /// /// 背景音乐 静音 /// /// public void MuteMusic(bool isMute) { if (backMusicSource == null) return; backMusicSource.mute = isMute; } /// /// 播放音效 /// /// 路径+音效文件名 不需要文件格式 /// 音效声音 /// 是否循环播放 /// 获取音效播放组件 public void PlaySound(string soundName, float volume = 1, bool isLoop = false, UnityAction action = null) { ResourcesManager.Instance.LoadAsync(soundName, (clip) => { AudioSource audioSource; if (audioSourcesCache.Count==0) { audioSource = musicObject.AddComponent(); audioSource.playOnAwake = false; audioSourcesCache.Add(audioSource); } audioSource = audioSourcesCache[0]; audioSourcesCache.RemoveAt(0); //设置声音大小 audioSource.volume = volume; //设置音效资源 audioSource.clip = clip; //循环 audioSource.loop = isLoop; //激活 audioSource.enabled = true; //播放 audioSource.Play(); //记录音效组件 这个有可能在多个地方同时调用 需要用锁 lock (this) { audioSources.Add(audioSource); } //播放音效后 获取音效组件 action?.Invoke(audioSource); }); } /// /// 暂停所有音效 /// public void PauseSound() { isPauseSound= true; lock (this) { for (int i = 0; i < audioSources.Count; i++) { audioSources[i].Pause(); } } } /// /// 重新播放所有正在播放的音效 /// public void UnPauseSounds() { isPauseSound = false; lock (this) { for (int i = 0; i < audioSources.Count; i++) { audioSources[i].UnPause(); } } } /// /// 静音 音效 /// /// public void MuteSound(bool isMute) { lock(this) { for (int i = 0; i < audioSources.Count; i++) { audioSources[i].mute = isMute; } } } /// /// 改变音效声音 /// /// public void ChangeSoundVolume(float volume) { lock (this) { for (int i = 0; i < audioSources.Count; i++) { audioSources[i].volume = volume; } } } /// /// 检测音效是否播放完 对播放完的音效进行删除 考虑性能 使用缓存池 /// private void Update() { lock (this) { for (int i = audioSources.Count-1 ; i >= 0; i--) { if (!audioSources[i].isPlaying && !isPauseSound) { audioSources[i].clip = null; audioSources[i].mute = false; audioSources[i].loop = false; audioSources[i].enabled = false; audioSourcesCache.Add(audioSources[i]); audioSources.RemoveAt(i); } } } } ~MusicManager() { MonoMgr.Instance.RemoveUpdateListener(Update); } }