unity中关于Audio模块的封装

Audio模块的封装
1、一个游戏中有且只有一个Aduiolistener,可以有多个相机

2、AduioSource非常的方便可以播放任意clip

3、但是由于它的属性很多,所有它占用的空间也非常大。并且AduioSource继承于MonoBehaviour,对于
MonoBehavriour,我们能不继承就不继承

所以我们先抽象出我们要解决的问题
抽象:目的是:能否使用有限个AudioSource来播放无限个clips
接下来我们建立一个AudioManager,下属一个SourceManager,一个ClipManager,SourceManager管理下属的有限个AudioManager,ClipManager管理下属的无限个clip,对于这种有多个相同的东西我们一般都会构造一个管理者。我们可以非常清楚的知道这是一个建造者模式,一层层的往下面构建,而SourceManager管理的东西和ClipsManager可以构建出一个音效,这就叫门面模式,而AudioMangaer作为一个模块的管理者,是属于管理者模式,也就是单例模式的。
接下来对SourceManager进行抽象化:
1、能够从AudioSources拿出一个空闲的AudioSource
2、释放多余的AudioSource
3、播放一个音效
4、停止播放一个音效

对ClipManager进行抽象化:
1、可以通过名字检索到我们要播放的clip
2、通过配置文件读取文件
3、加载到内存中

**AudioManager的具体实现代码
public class AudioManager:MonoBehaviour
{
public static AudioManager Instance;//实例化
SourceManager sourceManager;
ClipManager clipManager;
void Start()
{
Instance=this;
sourceManager=new SourceManager();
clipManager=new clipManager();
}
public void Play()//播放
{
AudioSource tmpSource=SourceManager.GetFree();
SingleClip tmpClip=ClipManager.FindClipByName(“名字”);]
if(tmpClip!=null)
{
tmpClip.Play(tmpSource);
}
}
public void Stop()//停止
{
}
}

public class SourceManager
{
public SourceManager(GameObject tmpObject )//析构函数
{
ower=tmpObject ;
Initual();
}
private List allSource;
private GameObject ower;
public void Initual()//初始化
{
for(int i=0;i<3;i++)
{
AudioSource tmpSource=ower.AddComponent();
allSource.Add(tmpSource);
}
}

public void Stop(string audioName)
{
for(int i=0;i<allSource.length;i++)
{
if(allSource[i].isPlaying&&allSource[i].clip.name.Equals(audioName))
{
allSource[i].Stop();
}
}
}

public AudioSource GetFreeAudio()//获取空闲的Audio
{
for(int i=0;i<allSource.length;i++)
{
if(!allSource.isPlaying)
{return allSource[i];}
}
AudioSource tmpSource=ower.AddComponent();
allSource.Add(tmpSource);
return tmpSource;
}

public void ReleaseFreeAudio()//删除多余的Audio
{
int tmpCount=0;
List tmpSources=new List();
for(int i=0;i<allSource.Count;i++)
{
if(!allSource.isPlaying)
{
tmpCount++;
}
if(tmpCount>3)
{
tmpSources.Add(allSource[i]);
}
}

for(int i=0;i<tmpSources.Count;i++)
{
AudioSource tmpSource=tmpSoures[i];
allSource.Remove(tmpSource);
GameObject.Destory(tmpSource);//删除场景中的Aduio
}
tmpSources.Clear();
tmpSources=null;

}
}

public class ClipManager
{
//从配置文件中读取
private string[] clipName;
private SingleClip[] allSingleClip;

public ClipManager()//析构函数
{
ReadConfig();
LoadClip();
}

//通过名字查找Clip
public SingleClip FindClipByName(string tmpName)
{
int tmpIndex=-1;
for(int i=0;i<clipName;i++)
{
if(clipName[i].Equals(tmpName))
{
tmpIndex=i;
}
}
if(tmpIndex!=-1)
{
return allSingleClip[tmpIndex];
}
}

public void LoadClip()//下载clip
{
allSingleClip=new SingleClip[clipName.lenght];
for(int i=0;i<clipName.lenght;i++)
{
AudioClip tmpClip=Reasources.Load(clipName[i]);
//clip文件别忘了放在Reasources文件夹内
SingleClip tmpSingle=new SingleClip(tmpClip);
allSingleClip[i]=tmpSingle;
}
}

public void ReadConfig()//读取配置文件
{
var fileAddress=System.IO.Path.Combine(Application.streamingAssetsPath,“AudioConfig.txt”);
//获取文件地址
FileInfo fInfoO=new FileInfo(fileAddress);
if(fInfoO.Exists)
{
StreamReader r=new StreamReader(fileAddress);
string tmpLine=r.ReadLine();//读取一行,记住读取了一行,后面就不会再重复读取了
int lineCount=0;
if(int.TryParse(tmpLine,out lineCount))
{
clipName=new string[lineCount];

   for(int i=0;i<lineCount)  //读取每一行,获取其中的文本
   {
   tmpLine=r.ReadLine();
   string [] splits=tmpLine.Split(" ");
   clipName[i]=splits[0];
   }
 }

}
r.Close();
}
}

public class SingleClip//保存AudioClip的类
{
AudioClip myClip;
public SingleClip(AudioClip tmpClip)
{
myClip=tmpClip;
}
//传过来一个空闲的AudioSource然后将它clip属性改为本身的Clip
public void Play(AudioSource tmpSource)
{
tmpSource.Clip=myClip;
}
}**

注:
1、遍历数组删除数组中的成员时,不要在循环里面删除数组成员,应该新建一个集合,来装着这个
该删除的数组,然后一次遍历删除。
2、int.TryParse(tmpLine,out lineCount)的意思就是试着解析这一行,把字符串转换为int类型,通过
out传输到lineCount里面去。
3、string [] splits=tmpLine.Split(" ");的意思就是划分,将文件中的一行通过空格划分成一个
字符串数组以便后续的操作。
4、之所以这里的clip,我们用SingleClip这样一个单独的类来进行存放,是因为后面这个Clip还有
play()等操作,所以还是将他用一个单独的类存放比较好
5、这里使用clipName对应allSingleClip,其实也相当于字典,一个是标记,一个是存在内存中,只是这种
速度更快一些。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值