在游戏开发中,音效是开发者需要仔细考虑的问题。一个大型的动作游戏,一个音效可能会出现成百上千遍。试想如果让我们的系统去实例化出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); } }
|
最后将脚本挂载到我们的音效预制体上、预制体拖入对象池上就大功告成了
