声音管理类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( "音效播放完了" );
}
}
