UFL6-2——音效管理模块音效部分实现
UFL6-2——音效管理模块音效部分实现
实现音效管理模块 音效 相关内容
主要实现内容
注意:
-
音效和背景音乐不同
音效存在多个,并且音效需要管理是否结束,因此需要用容器记录音效组件
-
音效分为循环和非循环
非循环的需要我们检测它播放结束,循环的需要让外部进行管理
-
播放音效
如果不考虑3D音效的话,可以将所有的音效源组件添加到一个单独的对象上,方便管理
每次播放音效时,都需要将播放音效的音效源组件添加到列表内,方便管理,同时还需要一个回调函数参数,将音效源组件传递出去1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28//用于音效组件依附的对象
private GameObject soundObj = null;
//管理正在播放的音效
private List<AudioSource> soundList = new List<AudioSource>();
//音效音量大小
private float soundVolume = 0.1f;
// 播放音效
public void PlaySound(string name, bool isLoop = false, bool isSync = false, UnityAction<AudioSource> callBack = null)
{
if (soundObj == null)
{
//音效依附的对象,一般过场景音效都需要停止,所以我们可以不处理,它过场景不移除
soundObj = new GameObject("soundObj");
}
//加载音效资源,进行播放
ABResManager.Instance.LoadResAsync<AudioClip>("sound", name, (clip) =>
{
AudioSource source = soundObj.AddComponent<AudioSource>();
source.clip = clip;
source.loop = isLoop;
source.volume = soundVolume;
source.Play();
//存储容器,用于记录,方便之后判断是否停止
soundList.Add(source);
callBack?.Invoke(source);
}, isSync);
} -
自动移除播放完成的音效
由于音效源没有播放完毕就执行的回调委托,我们必须每帧或者每隔一小段时间遍历检测音效是否播放完毕,将播放完毕的音效销毁并移除出列表
这里就会使用公共Mono模块的添加帧更新方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//管理正在播放的音效
private List<AudioSource> soundList = new List<AudioSource>();
private MusicManager()
{
//固定每一小段时间检测是否有音效播放完毕
MonoManager.Instance.AddFixedUpdateListener(Update);
}
private void Update()
{
//逆向遍历容器,检测是否有音效播放完毕了,如果播放完毕就销毁该组件并移除
for (int i = soundList.Count - 1; i >= 0; i--)
{
if (!soundList[i].isPlaying)
{
GameObject.Destroy(soundList[i]);
soundList.RemoveAt(i);
}
}
} -
停止播放指定音效
能够停止的音效必须是存在于列表内的
1
2
3
4
5
6
7
8
9
10
11
12
13//管理正在播放的音效
private List<AudioSource> soundList = new List<AudioSource>();
// 停止播放音效
public void StopSound(AudioSource source)
{
if (soundList.Contains(source))
{
source.Stop();
soundList.Remove(source);
GameObject.Destroy(source);
}
} -
设置音效声音大小
1
2
3
4
5
6
7
8
9
10
11
12
13//管理正在播放的音效
private List<AudioSource> soundList = new List<AudioSource>();
//音效音量大小
private float soundVolume = 0.1f;
public void ChangeSoundValue(float value)
{
soundVolume = value;
for (int i = 0; i < soundList.Count; i++)
{
soundList[i].volume = soundVolume;
}
} -
暂停或继续播放所有音效
注意,为我们在帧更新方法里使用音效源的
isPlaying
属性来判断是否需要销毁音效源,而暂停也会让isPlaying == false
因此,我们需要额外声明一个变量soundIsPlay
,用于控制帧更新销毁音效源的逻辑是否执行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45//管理正在播放的音效
private List<AudioSource> soundList = new List<AudioSource>();
//音效是否在播放,如果false说明在暂停
private bool soundIsPlay = true;
// 继续播放或者暂停所有音效
public void PlayOrPauseSound(bool isPlay)
{
soundIsPlay = isPlay;
if (isPlay)
{
for (int i = 0; i < soundList.Count; i++)
{
soundList[i].Play();
}
}
else
{
for (int i = 0; i < soundList.Count; i++)
{
soundList[i].Pause();
}
}
}
private MusicManager()
{
//固定每一小段时间检测是否有音效播放完毕
MonoManager.Instance.AddFixedUpdateListener(Update);
}
private void Update()
{
if (!soundIsPlay)
return;
//逆向遍历容器,检测是否有音效播放完毕了,如果播放完毕就销毁该组件并移除
for (int i = soundList.Count - 1; i >= 0; i--)
{
if (!soundList[i].isPlaying)
{
GameObject.Destroy(soundList[i]);
soundList.RemoveAt(i);
}
}
}
使用示例
准备几个音效文件,放到Assets/Editor/sound
文件夹下,以便于读取和打包
1 | private float v = 0.1f; |
通过点击屏幕上的绘制的按钮和滑动条,观察音效源控件的变化,监听音效变化
抛出问题
- 频繁的删除创建音效组件,比较浪费性能,应该如何优化?
- 3D音效需要让音效对象位置产生变化,我们应该如何修改?
具体代码
1 | using System.Collections; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!