之前做过的大大小小的项目,都会涉及到声音资源的播放,虽然播放声音片段技术含量不高,几步就能搞定,但如果每次建项目都需要写个声音播放类也比较麻烦,不同的项目可能也有不同的功能要求,有的只需要播放就行,再就是每次写的若有针对性,以后回看代码会降低效率,所以就把我以前所使用到的功能集合到一起,把声音播放功能做成一个预制体,即方便使用,也能统一方法。主要能实现声音的播放,暂停,停止,缓存,音量调节,循环,是否覆盖,播放完成回调等功能,后面若接触到新的需要还会继续添加迭代。

制作思路也比较简单,就是将音频播放分为不同的类型,如背景音,特效音,人物语言等等,每个类型的音频用一个AudioSourece播放,然后在播放的时候需要指出播放那个类型的音频,以及播放音频的文件名。

使用方式如下:

1,新建空组件GameObject(不限定),添加AudioPlayer脚本

AudioTrack播放器_声音管理类

2,约定一个音效类型(代码中会根据类型播放),如:bg,然后指定他的资源路径,最后点击“添加播放器”

AudioTrack播放器_AudioTrack播放器_02

点击后,GameObject下会出现一个子物体,名字是AS(audiosource)+你约定的音频类型名称,然后会自动挂上了AudioSource组件,挂上了本组件的配置信息脚本

AudioTrack播放器_audioplayer_03

3,使用方式如下:前两个参数是必填项,一个是播放声音的片段类型,他决定了在哪个AudioSource上面播放,第二个是声音片段的文件名

  

AudioTrack播放器_audioplayer_04

播放完成监听(每个使用类设置一个就行,不需要针对每个声音片段设置):需要将播放方法的是否监听设置为ture,然后该声音片段播发完成后result就能返回该片段名称

AudioTrack播放器_audioplayer_05

下面是AudioPlayer的源码,调用AudioPlay()方法进行播放,可以设置是否缓存,音量,是否循环,是否覆盖(若已经在播放该片段的情况下),播放完成后是否需要反馈。后面可调用方法分别是停止,暂停,继续播放,传入相应的声音类型即可。

public class AudioPlayer : MonoBehaviour
    {
        private static AudioPlayer _audioPlayer;
        private List<AudioItem> audioClasses;
        //public List<AudioOverListener> audioOverListeners;
        //public delegate void AudioOverListener(string name);
        public Action<string> AudioOverAction;

        private void Awake()
        {
            _audioPlayer = this.GetComponent<AudioPlayer>();
            audioClasses = new List<AudioItem>();
            foreach (Transform child in transform)
            {
                AudioItem audioItem = child.GetComponent<AudioItem>();
                audioClasses.Add(new AudioItem(audioItem.ResourceType, audioItem.ResourcePath, audioItem.ItemAudioSource));
            }
        }
        public static AudioPlayer GetInstance()
        {
            return _audioPlayer;
        }
        /// <summary>
        /// 播放声音片段方法
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="audioName">片段名称</param>
        /// <param name="cache">是否缓存</param>
        /// <param name="volume">音量</param>
        /// <param name="isLoop">是否循环</param>
        /// <param name="isCover">是否覆盖</param>
        /// <param name="isOverListener">是否需要播放完成回调监听</param>
        public void AudioPlay(string type, string audioName, bool cache = false, bool isLoop = false, bool isCover = true, bool isOverListener = false, float volume = 1)
        {
            foreach (AudioItem child in audioClasses)
            {
                if (child.ResourceType.Equals(type))
                {
                    AudioClip ac;
                    if (!child.AudioDic.TryGetValue(audioName, out ac))
                    {
                        ac = Resources.Load<AudioClip>(child.ResourcePath + "/" + audioName);
                        if (cache)
                        {
                            child.AudioDic.Add(audioName, ac);
                        }
                    }
                    else
                    {
                        ac = child.AudioDic[audioName];
                    }
                    if (child.ItemAudioSource != null)
                    {
                        if (!isCover && child.ItemAudioSource.isPlaying)
                        {
                            if (child.ItemAudioSource.clip.name.Equals(audioName)) return;
                        }
                        child.ItemAudioSource.clip = ac;
                        child.ItemAudioSource.loop = isLoop;
                        child.ItemAudioSource.volume = volume;
                        child.ItemAudioSource.Play();
                        if (isOverListener)
                            StartCoroutine(PlayBack(ac.name, ac.length));
                    }
                    break;
                }
            }
        }

        private IEnumerator PlayBack(string name, float length)
        {
            yield return new WaitForSeconds(length);
            AudioOverAction(name);
        }
        /// <summary>
        /// 结束
        /// </summary>
        /// <param name="type">音频类型</param>
        public void Stop(string type)
        {
            foreach (AudioItem child in audioClasses)
            {
                if (child.ResourceType.Equals(type))
                {
                    if (child.ItemAudioSource != null && child.ItemAudioSource.isPlaying)
                    {
                        child.ItemAudioSource.Stop();
                    }
                }
            }
        }
        /// <summary>
        /// 暂停
        /// </summary>
        /// <param name="type">音频类型</param>
        public void Pause(string type)
        {
            foreach (AudioItem child in audioClasses)
            {
                if (child.ResourceType.Equals(type))
                {
                    if (child.ItemAudioSource != null && child.ItemAudioSource.isPlaying)
                    {
                        child.ItemAudioSource.Pause();
                    }
                }
            }
        }
        /// <summary>
        /// 继续播放
        /// </summary>
        /// <param name="type">音频类型</param>
        public void Restart(string type)
        {
            foreach (AudioItem child in audioClasses)
            {
                if (child.ResourceType.Equals(type))
                {
                    if (child.ItemAudioSource != null)
                    {
                        child.ItemAudioSource.Play();
                        Debug.Log("继续播放");
                    }
                }
            }
        }
    }

下面是音频播放器Item属性,用来存放每个类型的播放器配置

/// <summary>
    /// 音频播放器Item属性
    /// </summary>
    [Serializable]
    public class AudioItem : MonoBehaviour
    {

        [SerializeField]
        private string resourceType;
        [SerializeField]
        private string resourcePath;
        [SerializeField]
        private AudioSource audioSource;
        [HideInInspector]
        private Dictionary<string, AudioClip> audioDic;
        private Action<string> audioOverAction;

        #region
        public AudioItem(string type, string path, AudioSource audios)
        {
            ResourceType = type;
            ResourcePath = path;
            ItemAudioSource = audios;
            audioDic = new Dictionary<string, AudioClip>();
        }


        public string ResourceType
        {
            get
            {
                return resourceType;
            }

            set
            {
                resourceType = value;
            }
        }

        public string ResourcePath
        {
            get
            {
                return resourcePath;
            }

            set
            {
                resourcePath = value;
            }
        }

        public AudioSource ItemAudioSource
        {
            get
            {
                return audioSource;
            }

            set
            {
                audioSource = value;
            }
        }

        public Dictionary<string, AudioClip> AudioDic
        {
            get
            {
                return audioDic;
            }

            set
            {
                audioDic = value;
            }
        }
        #endregion
    }

最后是音频播放器item生成工具,就是前面配置类型和路径然后点击“添加播放器”按钮生成子播放器的工具类

/// <summary>
    /// 音频播放器item生成工具
    /// </summary>
    [CustomEditor(typeof(AudioPlayer))]
    public class AddAudioPalyerItem : Editor
    {

        private static AddAudioPalyerItem _addAudioPalyerItem;
        public AddAudioPalyerItem GetInstance()
        {
            if (_addAudioPalyerItem == null)
            {
                _addAudioPalyerItem = new AddAudioPalyerItem();
            }
            return _addAudioPalyerItem;
        }

        private string typeText;
        private string pathText;
        /// <summary>
        /// <param name="音效类型">播放音效时需按指定类型播放,如bg,player等</param>
        /// <param name="资源路径">Resources下声音片段的具体路径文件夹,同个类型的音效放入同个资源路径</param>
        /// </summary>
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            typeText = EditorGUILayout.TextField("音效类型:", typeText);
            pathText = EditorGUILayout.TextField("资源路径:", pathText);

            if (isValue(typeText) & isValue(pathText))
            {
                if (GUILayout.Button("添加播放器"))
                {
                    GameObject go = new GameObject();
                    go.name = "AS_" + typeText;
                    go.AddComponent<AudioSource>().playOnAwake = false;
                    go.transform.parent = Selection.activeTransform;
                    go.AddComponent<AudioItem>();
                    go.GetComponent<AudioItem>().ResourcePath = pathText;
                    go.GetComponent<AudioItem>().ResourceType = typeText;
                    go.GetComponent<AudioItem>().ItemAudioSource = go.GetComponent<AudioSource>();
                    typeText = "";
                    pathText = "";
                }
            }
        }

        private bool isValue(string str)
        {
            if (str == null | str.Equals(""))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }

最后给出导出的unitypackage工具包百度网盘地址,是用unity2017.3.1导出的

https://pan.baidu.com/s/18EWw2YgrkjaIv8j2i7x8qw