5评论

全局音效管理器_001

萧然 2018-08-09 1k浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏开发行业精英群711501594

近期经常用到全局音效的管理问题,就直接写了一个管理器,因为是在小游戏里面使用,暂时只用到了这些功能,后面有机会以在继续补充··· 关于音效的动态加载,因为实际项目中并未用到(小游戏,采用序列化的方式),这里临时用Resources加载··· 话不多说,都在注释里 ```
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class AudioMgr : MonoBehaviour
{
    //序列化
    [Header("背景音乐")]
    [SerializeField] AudioClip backgroundMusic;
    [Header("音效")]
    [SerializeField] AudioClip[] audioClips;
    [Header("Resources加载路径")]
    [SerializeField] string clipResourcePath = "AudioClip";
    [Header("保留空闲播放器的数量")]
    [SerializeField] int emptySourceCount = 3;
    //播放器
    AudioSource baseSource;
    AudioSource bgmSource;
    //播放器list,音效Dictionary
    List<AudioSource> audioSourceList = new List<AudioSource>();
    Dictionary<string, AudioClip> audioClipDic = new Dictionary<string, AudioClip>();
    bool soundEnable;
    bool bgmEnable;
    string soundPlayerPrefsName = "soundPlayerPrefsName";
    string bgmPlayerPrefsName = "bgmPlayerPrefsName";
    //将该脚本挂载到场景GameObject,通过单例调用
    public static AudioMgr Instance;
    void Awake()
    {
        Instance = this;
    }
    void Start()
    {
        Init();
    }
    /*
    //若不需要序列化,音效采用动态加载的方式,可以不挂载该脚本,自动生成
    static AudioMgr instance;
    public static AudioMgr Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new GameObject("AudioMgr").AddComponent<AudioMgr>();
                instance.Init();
            }
            return instance;
        }
    }
    */
    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
            DestroyEmptySource();
        if (Input.GetKeyDown(KeyCode.Alpha2))
            PlaySound("2");
        if (Input.GetKeyDown(KeyCode.Alpha3))
            PlaySound("3");
        if (Input.GetKeyDown(KeyCode.Alpha4))
            SoundAudioEnable = !SoundAudioEnable;
        if (Input.GetKeyDown(KeyCode.Alpha5))
            BgmAudioEnable = !BgmAudioEnable;
    }
    public void Init()
    {
        //生成base播放器
        baseSource = new GameObject("BaseAudioSource").AddComponent<AudioSource>();
        baseSource.transform.parent = AudioMgr.Instance.transform;
        baseSource.playOnAwake = true;
        baseSource.loop = false;
        //BGM播放器
        bgmSource = Instantiate(baseSource, transform);
        bgmSource.gameObject.name = "BackgroundSource";
        bgmSource.loop = true;
        if (backgroundMusic != null)
            bgmSource.clip = backgroundMusic;
        ResetAudio();
    }
    //读取并还原开关设置状态
    void ResetAudio()
    {
        soundEnable = (PlayerPrefs.GetInt(soundPlayerPrefsName, 1) > 0) ? true : false; ;
        bgmEnable = (PlayerPrefs.GetInt(bgmPlayerPrefsName, 1) > 0) ? true : false; ;
        if (bgmEnable)
            bgmSource.Play();
    }
    //设置、获取 音效、背景音乐开关状态
    public bool SoundAudioEnable
    {
        get { return soundEnable; }
        set
        {
            if (soundEnable != value)
            {
                soundEnable = value;
                PlayerPrefs.SetInt(soundPlayerPrefsName, soundEnable ? 1 : 0);
            }
        }
    }
    public bool BgmAudioEnable
    {
        get { return bgmEnable; }
        set
        {
            if(bgmEnable != value)
            {
                bgmEnable = value;
                PlayerPrefs.SetInt(bgmPlayerPrefsName, bgmEnable ? 1 : 0);
                if(bgmEnable)
                    bgmSource.Play();
                else
                    bgmSource.Stop();
            }
        }
    }
    //播放音效(音效/名字)
    public void PlaySound(string clipName)
    {
        PlaySound(GetClipByName(clipName));
    }
    public void PlaySound(AudioClip clip)
    {
        if (soundEnable && clip!= null)
            StartCoroutine(PlayAndDisableSource(clip));
    }
    //设置背景音乐(音效/名字)
    public void SetBGMClip(string bgmName)
    {
        SetBGMClip(GetClipByName(bgmName));
    }
    public void SetBGMClip(AudioClip bgmClip)
    {
        if (bgmClip != null)
        {
            bgmSource.clip = bgmClip;
            BgmAudioEnable = true;
        }
    }
    //销毁多余空闲播放器,保留指定数量备用
    //可在指定条件下触发,或者利用定时器间隔固定时间进行清理
    public void DestroyEmptySource()
    {
        if (audioSourceList.Count > emptySourceCount)
        {
            for (int i = audioSourceList.Count - 1; i >= emptySourceCount; i--)
            {
                if (audioSourceList[i].enabled)
                    return;
                else
                {
                    Destroy(audioSourceList[i].gameObject);
                    audioSourceList.RemoveAt(i);
                }
            }
        }
    }
    // --------------
    //播放一段音效,并在播放完成后,回收播放器
    IEnumerator PlayAndDisableSource(AudioClip clip)
    {
        AudioSource audioSource = GetOneEmptySource();
        audioSource.clip = clip;
        audioSource.Play();
        while (audioSource.isPlaying)
        {
            yield return new WaitForEndOfFrame();
        }
        audioSource.enabled = false;
    }
    //获取一个空的播放器
    AudioSource GetOneEmptySource()
    {
        //遍历是否有空闲播放器
        for (int i = 0; i < audioSourceList.Count; i++)
        {
            if (!audioSourceList[i].enabled)
            {
                audioSourceList[i].enabled = true;
                return audioSourceList[i];
            }
        }
        //若没有,创建新的,并添加到list中统一管理
        AudioSource tmpGo = Instantiate(baseSource, transform);
        audioSourceList.Add(tmpGo);
        return tmpGo;
    }
    //通过名字获取音效片段
    AudioClip GetClipByName(string clipName)
    {
        //获取过的音效,将存在字典中,下次直接通过字典获取
        if (audioClipDic.ContainsKey(clipName))
        {
            return audioClipDic[clipName];
        }
        else
        {
            //面板序列化
            if(audioClips != null)
            {
                for (int i = 0; i < audioClips.Length; i++)
                {
                    if (clipName == audioClips[i].name)
                    {
                        audioClipDic.Add(audioClips[i].name, audioClips[i]);
                        return audioClips[i];
                    }
                }
            }
            Debug.Log("<color=blue> 未序列化该音效 </color>" + clipName);
            //Resources加载
            if (!string.IsNullOrEmpty(clipResourcePath))
            {
                AudioClip tmpNewAudioClip;
                tmpNewAudioClip = Resources.Load<AudioClip>(clipResourcePath + "/" + clipName);
                if (tmpNewAudioClip != null)
                {
                    audioClipDic.Add(clipName, tmpNewAudioClip);
                    return tmpNewAudioClip;
                }
                else
                    Debug.Log("<color=red> Resources加载失败 </color>" + clipName);
            }
            else
                Debug.Log("<color=blue> Resources路径为空 </color>" + clipName);
            return null;
        }
    }
}
```
若有任何意见或建议,欢迎分享讨论~~~