【Unity框架】音效系统搭建

在游戏开发中,音效是开发者需要仔细考虑的问题。一个大型的动作游戏,一个音效可能会出现成百上千遍。试想如果让我们的系统去实例化出1000个音效,无疑会给我们电脑带来很大的负担、这就是很容易崩溃的。那么我们需要用到缓存池技术(之前的文章有记载,点我跳转)。接下来我将结合缓存池技术,搭建一个简易好用的音效系统框架。


搭建思路

首先我们需要思考如何去搭建呢?
首先我们创建个空物体GamePool挂载上我们写的对象池脚本吧。
然后我们去想,需要做一个音效配置表,上面可以选择我们音频文件的类型和具体的音频文件,这一步写代码时就会想到要写一个enum和List的子类了。
之后我们去想,需要制作预制体文件,创造个ATK预制体,挂载上我们要写的Mono脚本。那么Mono脚本里需要什么呢?
第一点,我们Mono脚本需要给外部留出可编辑的部分,一个是音效类型、一个是挂载ScriptsObject文件;
之后我们需要写几行代码,根据我们在外部编辑界面传入的音效类型、去调用该类型下的音频文件,这一步我们直接放入音效配置表里写代码。
最后是具体音效的播放,我们通过在动画事件里传入一个string值,从而触发GamePoolManager里的TryGetPoolItem函数,对象池加载音效文件。

进行实践

首先我们制作一个音效配置表:

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
using NUnit.Framework;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "SoundData", menuName = "Scriptable Objects/SoundData")]
public class SoundData : ScriptableObject
{
[SerializeField]private List<Sound_Data> _data;

[System.Serializable]
private class Sound_Data
{
public SoundType soundType;
public AudioClip[] audioClip;
}
public AudioClip GetAudioClip(SoundType type)
{
//这里我在外部配置好了,List索引为0的是ATK,1是HIT,2是BLOCK,3是FOOT。如果你的跟我不一样自己改改
switch (type)
{
case SoundType.ATK:
return _data[0].audioClip[Random.Range(0, _data[0].audioClip.Length)];
case SoundType.HIT:
return _data[1].audioClip[Random.Range(0, _data[1].audioClip.Length)];
case SoundType.BLOCK:
return _data[2].audioClip[Random.Range(0, _data[2].audioClip.Length)];
case SoundType.FOOT:
return _data[3].audioClip[Random.Range(0, _data[3].audioClip.Length)];
}
return null;
}

}

接下来书写逻辑脚本

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
46
47
using UnityEngine;

//音效类型暂时写了四种
public enum SoundType
{
ATK,
HIT,
BLOCK,
FOOT
}
public class Sound : MonoBehaviour
{
private AudioSource audioSource;
//给外部提供可编辑的变量
[SerializeField]private SoundType soundType;
[SerializeField]private SoundData soundData;
private void Awake()
{
audioSource = GetComponent<AudioSource>();
}

private void OnEnable()
{
PlaySound(soundType);
}

//播放音效
private void PlaySound(SoundType type)
{
//这个GetAudioClip方法写在了音效编辑器里
audioSource.clip = soundData.GetAudioClip(type);
audioSource.Play();
StartRecycle();
}

//音效播放0.3秒后失活回收
private void StartRecycle()
{
TimerManager.Instance().TryGetOneTimer(0.3f, DisableSelf);
}

private void DisableSelf()
{
audioSource.Stop();
this.gameObject.SetActive(false);
}
}

最后将脚本挂载到我们的音效预制体上、预制体拖入对象池上就大功告成了