0
点赞
收藏
分享

微信扫一扫

全局音效管理器

近期经常用到全局音效的管理问题,就直接写了一个管理器,因为是在小游戏里面使用,暂时只用到了这些功能,后面有机会以在继续补充···

关于音效的动态加载,因为实际项目中并未用到(小游戏,采用序列化的方式),这里临时用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<AudioSource> audioSourceList = new List<AudioSource>();
Dictionary<string, AudioClip> audioClipDic = new Dictionary<string, AudioClip>();

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<AudioMgr>();
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<AudioSource>();
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("<color=blue> 未序列化该音效 </color>" + clipName);

//Resources加载
if (!string.IsNullOrEmpty(clipResourcePath))
{
AudioClip tmpNewAudioClip;
tmpNewAudioClip = Resources.Load<AudioClip>(clipResourcePath + "/" + clipName);
if (tmpNewAudioClip != null)
{
audioClipDic.Add(clipName, tmpNewAudioClip);
return tmpNewAudioClip;
}
else
Debug.Log("<color=red> Resources加载失败 </color>" + clipName);
}
else
Debug.Log("<color=blue> Resources路径为空 </color>" + clipName);
return null;
}
}

}

若有任何意见或建议,欢迎分享讨论~~~

-------------------- 分割线 --------------------

2019.9.11

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioHandler : MonoBehaviour
{
Dictionary<string, AudioClip> clipDic = new Dictionary<string, AudioClip>();

Queue<AudioSource> audioSourceQueue = new Queue<AudioSource>();

void Start()
{

}

public void Init()
{

}

public void Clear()
{
DestroyEmptySource();
}

public void PlayBtnClickSound()
{
PlaySound(ConstConfig.uiBtnClipName);
}

//播放音效(音效/名字)
public void PlaySound(string clipName)
{
PlaySound(GetClipByName(clipName));
}
public void PlaySound(AudioClip clip)
{
if (clip != null)
StartCoroutine(PlayAudioClip(clip));
}

//销毁多余空闲播放器
public void DestroyEmptySource()
{
List<AudioSource> audioSourceList = new List<AudioSource>(audioSourceQueue);

for (int i = audioSourceList.Count - 1; i >= 0; i--)
{
if (!audioSourceList[i].isPlaying)
{
Destroy(audioSourceList[i]);
audioSourceList.RemoveAt(i);
}
}

audioSourceQueue.Clear();
for (int i = 0; i < audioSourceList.Count; i++)
{
audioSourceQueue.Enqueue(audioSourceList[i]);
}
}

// --------------

//播放一段音效,并在播放完成后,回收播放器
IEnumerator PlayAudioClip(AudioClip clip)
{
AudioSource audioSource = GetEmptySource();

audioSource.loop = false;
audioSource.clip = clip;
audioSource.Play();

while (audioSource.isPlaying)
{
yield return new WaitForEndOfFrame();
}
yield return null;
audioSource.clip = null;
audioSourceQueue.Enqueue(audioSource);
}

//获取一个空的播放器
AudioSource GetEmptySource()
{
AudioSource tmpSource = null;
//是否有空闲播放器
if (audioSourceQueue.Count > 0)
{
tmpSource = audioSourceQueue.Dequeue();
}
else
{
//若没有,生成
tmpSource = gameObject.AddComponent<AudioSource>();
tmpSource.playOnAwake = false;
tmpSource.loop = false;
}
return tmpSource;
}

//通过名字获取音效片段
AudioClip GetClipByName(string clipName)
{
//获取过的音效,将存在字典中,下次直接通过字典获取
if (clipDic.ContainsKey(clipName))
{
return clipDic[clipName];
}
else
{
//Resources加载
AudioClip newClip = ResourcesLoader.LoadObject<AudioClip>(ConstConfig.audioClipPath, clipName);
if (newClip != null)
{
clipDic.Add(clipName, newClip);
return newClip;
}

Debug.Log("<color=red> Audio Clip == null </color>" + clipName);
return null;
}
}

}


举报

相关推荐

0 条评论