前置知识
1.每个场景有且只有一个Audio Listener
2.一个AudioSource 可以播放多种AudioClip
3.AudioSource有很多属性而且继承MonoBehavior,所以非常占用空间,所以少用
引出问题:
1.如何使用有限的AudioSouce播放无限个AudioClips
解决方案:
针对手游与vr进行的优化,默认加载三个AudioSource在AudioManager中.
如果想要播放音乐就把clip放入空闲的AudioSource中.
同时播放的clip如果超过了3个,那么就再次在AudioSource中添加一个AudioSource组件.
可通过命令清除空闲的组件以保证AudioSource不太占内存空间.
需求:
Audio管理器模块
设计图:
代码实现:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SingleClip {
AudioClip myClip;
public SingleClip(AudioClip tempClip)
{
myClip = tempClip;
}
public void Play(AudioSource audio)
{
audio.clip = myClip;
audio.Play();
}
}
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class ClipsManager {
string[] clipsName;
public ClipsManager()
{
ReadConfig();
LoadClips();
}
public void ReadConfig()
{
//地址
var fileAddress = Path.Combine(Application.streamingAssetsPath, "AudioConfig.txt");
//文件信息
FileInfo fInfo0 = new FileInfo(fileAddress);
//如果文件存在
if (fInfo0.Exists)
{
//开启读取
StreamReader r = new StreamReader(fileAddress);
string tempLine = r.ReadLine();
int lineCount = 0;
if (int.TryParse(tempLine,out lineCount))
{
clipsName = new string[lineCount];
for (int i = 0; i < lineCount; i++)
{
tempLine = r.ReadLine();
string[] splits = tempLine.Split(" ".ToCharArray());
clipsName[i] = splits[0];
}
}
//关闭文件
r.Close();
}
}
SingleClip[] allSingleClip;
public void LoadClips()
{
allSingleClip = new SingleClip[clipsName.Length];
for (int i = 0; i < clipsName.Length; i++)
{
AudioClip tempClip = Resources.Load<AudioClip>(clipsName[i]);
SingleClip singleClip = new SingleClip(tempClip);
allSingleClip[i] = singleClip;
}
}
public SingleClip FindClipByName(string clipName)
{
for (int i = 0; i < this.clipsName.Length; i++)
{
if(clipName == this.clipsName[i])
{
return allSingleClip[i];
}
}
return null;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SourcesManager
{
public SourcesManager(GameObject tempOwer)
{
ower = tempOwer;
Initial();
}
List<AudioSource> allSources;
GameObject ower;
public void Initial()
{
allSources = new List<AudioSource>();
for (int i = 0; i < 3; i++)
{
AudioSource source = ower.AddComponent<AudioSource>();
allSources.Add(source);
}
}
public AudioSource GerFreeAudio()
{
AudioSource source;
for (int i = 0; i < allSources.Count; i++)
{
if (!allSources[i].isPlaying)
{
return allSources[i];
}
}
source = ower.AddComponent<AudioSource>();
allSources.Add(source);
return source;
}
public void ReleaseFreeAudio()
{
List<AudioSource> freeSource = new List<AudioSource>();
int freeCount = 0;
for (int i = 0; i < allSources.Count; i++)
{
if (!allSources[i].isPlaying)
{
freeCount++;
if (freeCount > 3)
{
freeSource.Add(allSources[i]);
}
}
}
for (int j = 0; j < freeSource.Count; j++)
{
AudioSource source = freeSource[j];
allSources.Remove(source);
GameObject.Destroy(source);
}
freeSource.Clear();
freeSource = null;
}
public void Stop(string audioName)
{
for (int i = 0; i < allSources.Count; i++)
{
if(allSources[i].isPlaying && audioName == allSources[i].clip.name)
{
allSources[i].Stop();
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudiosManager : MonoBehaviour {
public AudiosManager Instance;
SourcesManager sourcesManager;
ClipsManager clipsManager;
private void Start()
{
Instance = this;
sourcesManager = new SourcesManager(gameObject);
clipsManager = new ClipsManager();
}
public void Play(string audioName)
{
//取得一个空闲的AudioSource
AudioSource tempSource = sourcesManager.GerFreeAudio();
//根据名字的到clip
SingleClip tempClip = clipsManager.FindClipByName(audioName);
//播放
tempClip.Play(tempSource);
}
public void Stop(string audioName)
{
sourcesManager.Stop(audioName);
}
public void ReleaseFreeAudio()
{
sourcesManager.ReleaseFreeAudio();
}
private void Update()
{
//测试
if (Input.GetKeyDown(KeyCode.A))
{
Play("0");
}
if (Input.GetKeyDown(KeyCode.S))
{
Play("1");
}
if (Input.GetKeyDown(KeyCode.D))
{
Play("2");
}
if (Input.GetKeyDown(KeyCode.C))
{
ReleaseFreeAudio();
}
if (Input.GetKeyDown(KeyCode.X))
{
Stop("1");
}
}
}