Unity 工具类 之 简单的音频播放管理框架/仅通过音频名即可播放和停止(音效背景音乐复用AudioSource对象池)
目录
一、简单介绍
Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。
一个音频播放管理类,管理音频的播放和停止,只要传一个音频名字即可实现播放和停止。
二、实现原理
1、类似一个音频名播放使用接口:AudioPlayManager.Instance.Play("Click", true);
2、类似一个音频名播放使用接口:AudioPlayManager.Instance.Stop("Click");(当然背景音乐播放使用何必要)
3、AudioSourceManager 类管理 AudioSource 对象池,的获取对象,释放对象等
4、AudioClipManager 读取音频配置文件游戏图片素材,加载对应音频资源,管理音频资源
5、简单框架和说明如下
三、注意事项
1、如果的音频足够简单,可以 只要两个 AudioSource,固定一个作为背景音乐播放,一个作为音效播放,而可以不用对象池
2、如果你的音频很多,也不是同时马上用到,可以不用马上全加载到内存中,可以使用的时候才加载,常用的才缓存到起来
3、音频的配置文件内容格式多样,可以csv、json ,必要可以在加密数据使用
4、注意,如果使用本例的配置文件形式unity按钮点击音效,因为配置文件的音频路径在后面开发学习,分割字符串保存加载路径的时候,一定要吧结尾的 \n 裁剪掉(namesPaths[1].Trim()),不然加载不到资源,这个被坑了很久才发现(打印输出都没有看出,后面复制打印结果粘贴到代码中才发现(粘贴自动回车换行,才恍然大悟,不容易啊)),请注意哈,不要再踩坑了哈
四、效果预览
五、实现步骤
1、打开Unity,新建一个空工程
2、在场景中,添加两个按钮,一个Play,一个Stop
3、在场景中,导入音频资源和配置文件
4、在工程中添加脚本,各司其能unity按钮点击音效,实现音频播放
5、把 TestAudioPlayManager 挂载到场景中,并对应赋值
6、运行场景,效果如上
六、关键代码
1、TestAudioPlayManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TestAudioPlayManager : MonoBehaviour
{
public Button PlayButton;
public Button StopButton;
// Start is called before the first frame update
void Start()
{
PlayButton.onClick.AddListener(()=> {
AudioPlayManager.Instance.Play("Click", true);
});
StopButton.onClick.AddListener(() => {
AudioPlayManager.Instance.Stop("Click");
});
}
}
2、AudioPlayManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioPlayManager : MonoSingleton
{
AudioSourceManager mAudioSourceManager;
AudioClipManager mAudioClipManager;
protected override void Awake()
{
base.Awake();
mAudioSourceManager = new AudioSourceManager(this.gameObject);
mAudioClipManager = new AudioClipManager();
}
public void Play(string audioName,bool isLoop = false) {
Debug.Log(GetType()+ "/Play()/ audioName : "+ audioName);
SingleClip clip = mAudioClipManager.GetAudioByName(audioName);
AudioSource source = mAudioSourceManager.GetIdleAudioSource();
clip?.Play(source, isLoop);
}
public void Stop(string audioName) {
Debug.Log(GetType() + "/Stop()/ audioName : " + audioName);
mAudioSourceManager.Stop(audioName);
}
}
3、AudioSourceManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioSourceManager
{
List allSourcesLst;
GameObject owner;
public AudioSourceManager(GameObject owner) {
this.owner = owner;
Init();
}
///
/// 初始化列表,并预加载两个 AudioSource
///
void Init() {
allSourcesLst = new List();
for (int i = 0; i < 2; i++)
{
AudioSource item = owner.AddComponent();
allSourcesLst.Add(item);
}
}
///
/// 获得闲置的 AudioSource
///
///
public AudioSource GetIdleAudioSource() {
//Debug.Log(GetType() + "/GetIdleAudioSource()/");
for (int i = 0; i < allSourcesLst.Count; i++)
{
if (allSourcesLst[i].isPlaying == false)
{
return allSourcesLst[i];
}
}
AudioSource item = owner.AddComponent();
allSourcesLst.Add(item);
return item;
}
///
/// 释放多余的 AudioSource
/// 包正列表中不会有太多 AudioSource
///
public void ReleaseUnnecessaryAudioSource() {
int tmpCount = 0;
List tmpSourceLst = new List();
for (int i = 0; i < allSourcesLst.Count; i++)
{
if (allSourcesLst[i].isPlaying == false)
{
tmpCount++;
if (tmpCount > 3)
{
tmpSourceLst.Add(allSourcesLst[i]);
}
}
}
for (int i = 0; i < tmpSourceLst.Count; i++)
{
AudioSource item = tmpSourceLst[i];
allSourcesLst.Remove(item);
GameObject.Destroy(item);
}
tmpSourceLst.Clear();
tmpSourceLst = null;
}
public void Stop(string audioName) {
if (string.IsNullOrEmpty(audioName)==false)
{
for (int i = 0; i < allSourcesLst.Count; i++)
{
if (allSourcesLst[i].isPlaying ==true && allSourcesLst[i].clip.name.Equals(audioName))
{
allSourcesLst[i].Stop();
}
}
}
}
}
4、AudioClipManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioClipManager
{
const string cfgPath = "AudioClip/AudioClipCfg";
Dictionary clipNamePathDic;
Dictionary clipNameAudioDic;
string[] clipPathLst;
public AudioClipManager() {
clipNamePathDic = new Dictionary();
clipNameAudioDic = new Dictionary();
ReadConfig();
LoadClip();
}
public SingleClip GetAudioByName(string clipName) {
SingleClip item = null;
clipNameAudioDic.TryGetValue(clipName, out item);
return item;
}
void ReadConfig() {
string strConfig = Resources.Load(cfgPath).text;
string[] linesStr = strConfig.Split('\n');
int clipCount = 0;
if (int.TryParse(linesStr[0],out clipCount)==true)
{
clipPathLst = new string[clipCount];
for (int i = 1; i <= clipCount; i++)
{
string[] namesPaths = linesStr[i].Split(':');
clipNamePathDic.Add(namesPaths[0], namesPaths[1].Trim());
clipPathLst[i-1] = namesPaths[1];
}
}
}
void LoadClip() {
foreach (var item in clipNamePathDic)
{
Debug.Log(GetType() + "/LoadClip()/item.Value == " + item.Value);
AudioClip clip = Resources.Load(item.Value);
SingleClip singleClip = new SingleClip(clip);
clipNameAudioDic.Add(item.Key, singleClip);
}
// clipNamePathDic 这个可能用不上了,可以清空,避免一直占用内存
clipNamePathDic.Clear();
clipNamePathDic = null;
}
}
5、SingleClip
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SingleClip
{
AudioClip clip;
public SingleClip(AudioClip clip) {
this.clip = clip;
}
public void Play(AudioSource audioSource,bool isLoop=false) {
audioSource.clip = clip;
audioSource.loop = isLoop;
audioSource.Play();
}
}
6、AudioClipCfg
3
ChangePage:AudioClip/ChangePage
Click:AudioClip/Click
Hover:AudioClip/Hover
文章来源:https://blog.csdn.net/u014361280/article/details/109517579