声音管理类AudioManager
发表于2017-09-30
今天给大家分享下刚刚做的AudioManager
实现了以下功能:
1.同时播放一首背景音乐
2.同时播放N个音效
3.对象池管理AudioSource组件
4.背景音乐的声音淡入淡出
5.调整背景音乐的音量
6.调整音效的音量
7.本地缓存声音音量
8.切换场景不销毁
9.获取播放音效结束回调
10.播放3d音效
使用方法: 直接挂载到空物体上
应该是实现了大部分项目中需要的声音管理类的功能
下面为实现的代码
using UnityEngine; using System.Collections; using System.Collections.Generic; using DG.Tweening; using System; public class AudioManager : MonoBehaviour { private static AudioManager instance; public static AudioManager Instance { get { return instance; } } private Dictionary<int, string> audioPathDict; // 存放音频文件路径 private AudioSource musicAudioSource; private List<AudioSource> unusedSoundAudioSourceList; // 存放可以使用的音频组件 private List<AudioSource> usedSoundAudioSourceList; // 存放正在使用的音频组件 private Dictionary<int, AudioClip> audioClipDict; // 缓存音频文件 private float musicVolume = 1; private float soundVolume = 1; private string musicVolumePrefs = "MusicVolume"; private string soundVolumePrefs = "SoundVolume"; private int poolCount = 3; // 对象池数量 void Awake() { DontDestroyOnLoad( this.gameObject ); instance = this; audioPathDict = new Dictionary<int, string>() // 这里设置音频文件路径。需要修改。 TODO { { 1, "AudioClip/Music/MainMenuScene" }, { 2, "AudioClip/Music/BattleScene" }, { 11, "AudioClip/Sound/Sound1"}, { 12, "AudioClip/Sound/Sound2"}, { 13, "AudioClip/Sound/Sound3"}, { 14, "AudioClip/Sound/Sound4"}, { 15, "AudioClip/Sound/Sound5"}, }; musicAudioSource = gameObject.AddComponent<AudioSource>(); unusedSoundAudioSourceList = new List<AudioSource>(); usedSoundAudioSourceList = new List<AudioSource>(); audioClipDict = new Dictionary<int, AudioClip>(); } void Start() { // 从本地缓存读取声音音量 if ( PlayerPrefs.HasKey( musicVolumePrefs ) ) { musicVolume = PlayerPrefs.GetFloat( musicVolumePrefs ); } if ( PlayerPrefs.HasKey( soundVolumePrefs ) ) { musicVolume = PlayerPrefs.GetFloat( soundVolumePrefs ); } } /// <summary> /// 播放背景音乐 /// </summary> /// <param name="id"></param> /// <param name="loop"></param> public void PlayMusic( int id, bool loop = true ) { // 通过Tween将声音淡入淡出 DOTween.To( () => musicAudioSource.volume, value => musicAudioSource.volume = value, 0, 0.5f ).OnComplete( () => { musicAudioSource.clip = GetAudioClip( id ); musicAudioSource.clip.LoadAudioData(); musicAudioSource.loop = loop; musicAudioSource.volume = musicVolume; musicAudioSource.Play(); DOTween.To( () => musicAudioSource.volume, value => musicAudioSource.volume = value, musicVolume, 0.5f ); } ); } /// <summary> /// 播放音效 /// </summary> /// <param name="id"></param> public void PlaySound( int id, Action action = null ) { if ( unusedSoundAudioSourceList.Count != 0 ) { AudioSource audioSource = UnusedToUsed(); audioSource.clip = GetAudioClip( id ); audioSource.clip.LoadAudioData(); audioSource.Play(); StartCoroutine( WaitPlayEnd( audioSource, action ) ); } else { AddAudioSource(); AudioSource audioSource = UnusedToUsed(); audioSource.clip = GetAudioClip( id ); audioSource.clip.LoadAudioData(); audioSource.volume = soundVolume; audioSource.loop = false; audioSource.Play(); StartCoroutine( WaitPlayEnd( audioSource, action ) ); } } /// <summary> /// 播放3d音效 /// </summary> /// <param name="id"></param> /// <param name="position"></param> public void Play3dSound( int id, Vector3 position ) { AudioClip ac = GetAudioClip( id ); AudioSource.PlayClipAtPoint( ac, position ); } /// <summary> /// 当播放音效结束后,将其移至未使用集合 /// </summary> /// <param name="audioSource"></param> /// <returns></returns> IEnumerator WaitPlayEnd( AudioSource audioSource, Action action ) { yield return new WaitUntil( () => { return !audioSource.isPlaying; } ); UsedToUnused( audioSource ); if ( action != null ) { action(); } } /// <summary> /// 获取音频文件,获取后会缓存一份 /// </summary> /// <param name="id"></param> /// <returns></returns> private AudioClip GetAudioClip( int id ) { if ( !audioClipDict.ContainsKey( id ) ) { if ( !audioPathDict.ContainsKey( id ) ) return null; AudioClip ac = Resources.Load( audioPathDict[id] ) as AudioClip; audioClipDict.Add( id, ac ); } return audioClipDict[id]; } /// <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> 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> public void ChangeMusicVolume( float volume ) { musicVolume = volume; musicAudioSource.volume = volume; PlayerPrefs.SetFloat( musicVolumePrefs, volume ); } /// <summary> /// 修改音效音量 /// </summary> /// <param name="volume"></param> public 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 ); } }
调用方法
using UnityEngine; using System.Collections; public class NewBehaviourScript : MonoBehaviour { // Use this for initialization void Start () { AudioManager.Instance.PlayMusic( 1 ); AudioManager.Instance.PlaySound( 11, OnSoundPlayEnd ); AudioManager.Instance.ChangeMusicVolume( 0.5f ); AudioManager.Instance.ChangeSoundVolume( 0.5f ); } void OnSoundPlayEnd() { Debug.Log( "音效播放完了" ); } }