近期经常用到全局音效的管理问题,就直接写了一个管理器,因为是在小游戏里面使用,暂时只用到了这些功能,后面有机会以在继续补充···
关于音效的动态加载,因为实际项目中并未用到(小游戏,采用序列化的方式),这里临时用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;
}
}
}
若有任何意见或建议,欢迎分享讨论~~~