Unity3d声音管理器AudioManager

播放背景音乐、播放提示音、播放音效。成组播放、声音源复用、音量控制、音效播放位置等等。

写差不多了,发现不是自己想要的风格。没完善呢就过时的感觉。先放着吧。。。

#if UNITY_EDITOR
//#define Sirenix_OdinInspector
#endif

#if Sirenix_OdinInspector
using Sirenix.OdinInspector;
#endif
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

/// 
/// 声音管理器
/// (目前不保证稳定,出现问题可尝试"try{}catch{AudioManager.ForceReset();}")
/// 
public class AudioManager :

#if Sirenix_OdinInspector
    SerializedMonoBehaviour
#else
    MonoBehaviour
#endif
{
    public static AudioManager Instance
    {
        get
        {
            CreatAudioManager();
            return instance;
        }
    }
#if Sirenix_OdinInspector
#elif UNITY_EDITOR
    [Header("注意!不要在面板上修改任何值!面板仅为方便观察"),Space(10)]
#endif
    public const int ID_WHEN_NULL = -1;

    #region 设置项
    /// 
    /// 读取默认配置
    /// 
    private void LoadConfig()
    {
        MuteSound = PlayerPrefs.GetInt("MuteSound") > 0 ? true : false;
        SoundVolume = PlayerPrefs.GetFloat("SoundVolume");
        MuteMusic = PlayerPrefs.GetInt("MuteMusic") > 0 ? true : false;
        MusicVolume = PlayerPrefs.GetFloat("MuteSound");
    }
    private void SaveConfig()
    {
        PlayerPrefs.SetInt("MuteSound", MuteSound ? 1 : 0);
        PlayerPrefs.SetFloat("SoundVolume", SoundVolume);
        PlayerPrefs.SetInt("MuteSound", MuteMusic ? 1 : 0);
        PlayerPrefs.SetFloat("MuteSound", MusicVolume);
        PlayerPrefs.Save();
    }
    /// 
    /// 音效静音
    /// 
    public bool MuteSound
    {
        get
        {
            return muteSound;
        }

        set
        {
            if (muteSound == value)
                return;
            needSave = true;
            saveTime = 0;
            muteSound = value;
            if (!muteSound)
                return;
            for (int i = 0; i < playingAudio.Count; i++)
            {
                if (playingAudio != null
                    && !playingAudio[i].IsMusic)
                {
                    playingAudio[i].Stop(0, true);
                }
            }
        }
    }
    /// 
    /// 音效音量
    /// 
    public float SoundVolume
    {
        get
        {
            return soundVolume;
        }

        set
        {
            if (soundVolume == value)
                return;
            needSave = true;
            saveTime = 0;
            soundVolume = value;
        }
    }
    /// 
    /// 背景音乐静音
    /// 
    public bool MuteMusic
    {
        get
        {
            return muteMusic;
        }

        set
        {
            if (muteMusic == value)
                return;
            needSave = true;
            saveTime = 0;
            muteMusic = value;
            if (!muteMusic)
                return;
            for (int i = 0; i < playingAudio.Count; i++)
            {
                if (playingAudio != null
                    && playingAudio[i].IsMusic)
                {
                    playingAudio[i].Stop(2, false);
                }
            }
        }
    }
    /// 
    /// 背景音乐声音大小
    /// 
    public float MusicVolume
    {
        get
        {
            return musicVolume;
        }

        set
        {
            if (musicVolume == value)
                return;
            needSave = true;
            saveTime = 0;
            musicVolume = value;
        }
    }
    #endregion 设置项

    #region 全局工具
    public void Init()
    {
        idPointer = 0;
        AudioControllerDic.Clear();
        LoadConfig();
        OnInit();
        //PerLoad();
    }
    /// 
    /// 重置
    /// 
    public void ForceReset()
    {
        while (sourceCachePool.Count > 0)
        {
            sourceCachePool.Dequeue().Release();
        }
        playingMusic = null;
        playingBGSound = null;
        for (int i = 0; i < playingAudio.Count; i++)
        {
            if (playingAudio[i] != null)
                playingAudio[i].Release();
        }
        playingAudio.Clear();
        audioClipPool.Clear();

        poolTotalCount = 0;
        audioTotalCount = 0;
        recordTimes = 0;
        lastRecordTime = 0;
        Init();
    }
    /// 
    /// 停止所有声音
    /// 
    public void StopAll()
    {
        for (int i = 0; i < playingAudio.Count; i++)
        {
            if (playingAudio[i] != null)
            {
                playingAudio[i].Stop(1, false);
            }
        }
    }
    /// 
    /// 让某声音控制器停止播放
    /// 
    /// 声音控制器ID
    /// 过渡时间
    /// 是否等待播放完成
    public void StopAudio(int id, float transitionTime = 0, bool waitFinished = false)
    {
        if (id == ID_WHEN_NULL)
            return;
        if (!AudioControllerDic.ContainsKey(id))
            return;
        if (AudioControllerDic[id] == null)
            return;
        AudioControllerDic[id].Stop(transitionTime, waitFinished);
    }
    #endregion 全局工具

    #region 背景音乐相关接口
    /// 
    /// 播放背景音乐
    /// 
    /// 音频文件名
    /// 过渡时间
    /// 声音控制器ID
    public int PlayBackGroundMusic(string clipName, float transitionTime = 1)
    {
        if (MuteMusic)
            return ID_WHEN_NULL;

        if (clipName == null)
            return ID_WHEN_NULL;

        if (IsPlayingBGM(clipName))
            return playingMusic.ID;

        if (transitionTime < 0)
            transitionTime = 0;

        if (playingMusic != null)
            playingMusic.Stop(transitionTime, false);

        playingMusic = GetController();
        playingMusic.SetMusic(transitionTime, false, true, GetClip(clipName));
        return playingMusic.ID;
    }
    /// 
    /// 是否正在播放
    /// 
    /// 
    public bool IsPlayingBGM()
    {
        if (MuteMusic)
            return false;
        if (playingMusic == null)
            return false;
        return playingMusic.IsPlaying();
    }
    /// 
    /// 是否正在播放背景音乐
    /// 
    /// 
    public bool IsPlayingBGM(string clipName)
    {
        if (MuteMusic)
            return false;
        if (playingMusic == null)
            return false;
        return playingMusic.IsPlaying(clipName);
    }
    /// 
    /// 停止播放
    /// 
    /// 是否等待播放完成再停止
    public void StopBGM(bool waitEnd = false)
    {
        if (playingMusic == null)
            return;
        playingMusic.Stop(2, waitEnd);
    }
    /// 
    /// 得到当前正在播放的背景音乐
    /// 
    /// 
    public string GetCurrBGM()
    {
        if (MuteMusic)
            return null;
        if (playingMusic == null)
            return null;
        if (!playingMusic.IsPlaying())
            return null;
        if (playingMusic.audioClips == null)
            return null;
        if (playingMusic.CurrIdex >= playingMusic.audioClips.Length)
            return playingMusic.audioClips[0].name;
        return playingMusic.audioClips[playingMusic.CurrIdex].name;
    }

    /// 
    /// 加入背景音乐播放队列
    /// 
    /// 
    /// 
    public void PlayQueuedBGM(string clipName, float transitionTime = 0)
    {
        if (MuteMusic)
            return;
        /* */
    }

    #endregion 背景音乐相关接口

    #region 音效相关接口
    /// 
    /// 是否正在播放背景音效
    /// 
    /// 
    public bool IsPlayingRandomSound()
    {
        if (MuteSound)
            return false;
        if (playingBGSound == null)
            return false;
        return playingBGSound.IsPlaying();
    }
    /// 
    /// 得到当前正在播放的背景音效
    /// 
    /// 
    public string[] GetCurrRandomSound()
    {
        if (MuteSound)
            return null;
        if (playingBGSound == null)
            return null;
        if (!playingBGSound.IsPlaying())
            return null;
        if (playingBGSound.audioClips == null)
            return null;
        string[] tmp = new string[playingBGSound.audioClips.Length];
        for (int i = 0; i < tmp.Length; i++)
        {
            if (playingBGSound.audioClips[i] != null)
                tmp[i] = playingBGSound.audioClips[i].name;
        }
        return tmp;
    }
    /// 
    /// 播放随机背景音效(2D)
    /// 随机间隔随机播放音效
    /// 
    /// 声音片段名,为null不播放
    /// 最小播放间隔
    /// 最大播放间隔
    /// 声音控制器ID
    public int PlayRandomSound(string[] clipNames, float minInterval, float maxInterval)
    {
        if (MuteSound)
            return ID_WHEN_NULL;
        if (playingBGSound != null)
        {
            playingBGSound.Stop(0, true);
        }
        if (clipNames == null || clipNames.Length == 0)
        {
            playingBGSound = null;
            return ID_WHEN_NULL;
        }
        playingBGSound = GetController();

        playingBGSound.SetSound(null, Vector3.zero, 0, true, 1, true, 1, GetClip(clipNames));
        playingBGSound.SetInterval(minInterval, maxInterval);
        return playingBGSound.ID;
    }
    /// 
    /// 播放一个2D音效
    /// 用于播放提示音等
    /// 
    public int PlaySound(string clipName, float volume = 1)
    {
        if (MuteSound)
            return ID_WHEN_NULL;
        if (clipName == null)
            return ID_WHEN_NULL;
        AudioController audioController = GetController();

        audioController.SetSound(null, Vector3.zero, 0, true, 1, true, volume, GetClip(clipName));
        return audioController.ID;
    }
    public int PlaySound(string clipName, Transform target, Vector3 pos, float volume = 1, float pitch = 1)
    {
        if (MuteSound)
            return ID_WHEN_NULL;
        if (clipName == null)
            return ID_WHEN_NULL;
        AudioController audioController = GetController();
        audioController.SetSound(target, pos, 1, false, pitch, false, volume, GetClip(clipName));
        return audioController.ID;
    }

    public int PlaySound(string[] clipName, Transform target, Vector3 pos, float length = 0, bool random = false, float volume = 1, float pitch = 1)
    {
        if (MuteSound)
            return ID_WHEN_NULL;
        if (clipName == null)
            return ID_WHEN_NULL;
        AudioController audioController = GetController();
        audioController.SetSound(target, pos, 1, random, pitch, false, volume, GetClip(clipName));
        if (length > 0)
            audioController.SetRemainingLength(length, 0);
        return audioController.ID;
    }

    #endregion 音效相关接口

    #region 私有成员


    private bool muteSound = false;
    private float soundVolume = 1;
    private bool muteMusic = false;
    private float musicVolume = 1;
    private float saveTime = 0;
    private bool needSave = false;
#if Sirenix_OdinInspector
    [SerializeField, ReadOnly]
#else
    [SerializeField]
#endif
    private Dictionary AudioControllerDic = new Dictionary();

    private static AudioManager instance;
    private static void CreatAudioManager()
    {
        if (instance == null)
        {
            AudioManager[] audioManagers = FindObjectsOfType();
            if (audioManagers != null && audioManagers.Length > 0)
            {
                instance = audioManagers[0];
                DontDestroyOnLoad(instance.gameObject);
                if (audioManagers.Length > 1)
                {
                    Debug.Log("场景中存在多余的AudioManager");
                }
            }
            else
            {
                GameObject obj = new GameObject("AudioManager");
                DontDestroyOnLoad(obj);
                instance = obj.AddComponent();
            }
        }
    }
    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        OnAwake();
    }

    #region 生命周期
    private void OnAwake()
    {

    }
    private void OnInit()
    {

    }
    private void Update()
    {
        //驱动AudioController
        for (int i = 0; i < playingAudio.Count; i++)
        {
            if (playingAudio[i] == null)
                continue;
            //更新
            playingAudio[i].OnUpdate(Time.deltaTime);

            //判断更新结果
            if (playingAudio[i].IsDestroyed)
            {
                playingAudio[i] = null;
                continue;
            }

            if (playingAudio[i].IsPlayFinished ||
                playingAudio[i].IsReleased)
            {
                Lose(playingAudio[i]);
            }
        }
        //缓存池
        UpdateCache(Time.deltaTime);
        //延迟保存配置项
        if (needSave)
        {
            saveTime += Time.deltaTime;
            if (saveTime > 10)
            {
                SaveConfig();
                needSave = false;
                saveTime = 0;
            }
        }
    }

    #endregion 生命周期

    #region 缓存池
    /*
     * 作用是创建AudioSource、AudioClip,回收AudioSource、AudioClip,减少实例和销毁频率
     * 如果缓存了过多的对象,要定时清理
     */
#if Sirenix_OdinInspector
    [SerializeField, ReadOnly]
#elif UNITY_EDITOR
    [SerializeField]
#endif
    private AudioController playingMusic;//不会有两个背景音乐同时播放
#if Sirenix_OdinInspector
    [SerializeField, ReadOnly]
#elif UNITY_EDITOR
    [SerializeField]
#endif
    private AudioController playingBGSound;
#if Sirenix_OdinInspector
    [SerializeField, ReadOnly]
#elif UNITY_EDITOR
    [SerializeField]
#endif
    private readonly Dictionary audioClipPool = new Dictionary();
    private readonly List playingAudio = new List();
    private readonly Queue sourceCachePool = new Queue();
    /// 
    /// 预加载
    /// 
    private void PerLoad()
    {
        for (int i = 0; i < 5; i++)
        {
            Lose(CreatAudioController());
        }
    }

    private uint poolTotalCount = 0;
    private uint audioTotalCount = 0;
    private uint recordTimes = 0;
    private float lastRecordTime = 0;
    private int idPointer = 0;
    /// 
    /// 这样会不会增多GC?
    /// 
    /// 
    private void UpdateCache(float deltaTime)
    {
        if (Time.realtimeSinceStartup - lastRecordTime < 20)
            return;
        lastRecordTime = Time.realtimeSinceStartup;
        recordTimes++;
        poolTotalCount += (uint)sourceCachePool.Count;
        poolTotalCount += (uint)playingAudio.Count;


        if (sourceCachePool.Count > poolTotalCount / recordTimes * 1.25f)
        {
            int n = sourceCachePool.Count / 4;
            for (int i = 0; i < n; i++)
            {
                sourceCachePool.Dequeue().Release();
            }
        }

        if (playingAudio.Count > audioTotalCount / recordTimes * 1.25f)
        {
            playingAudio.RemoveAll((AudioController a) => { return a == null; });
        }

        if (recordTimes > 15)
        {
            poolTotalCount = 0;
            audioTotalCount = 0;
            recordTimes = 0;
        }
    }
    private AudioController AddPlayingAudioList(AudioController audioController)
    {
        if (playingAudio.Contains(audioController))
            return audioController;
        for (int i = 0; i < playingAudio.Count; i++)
        {
            if (playingAudio == null)
            {
                playingAudio[i] = audioController;
                return audioController;
            }
        }
        playingAudio.Add(audioController);
        return audioController;
    }
    private AudioController GetController()
    {
        if (sourceCachePool.Count == 0)
        {
            return AddPlayingAudioList(CreatAudioController());
        }
        AudioController audioController;
        for (int i = 0; i < sourceCachePool.Count; i++)
        {
            audioController = sourceCachePool.Dequeue();
            if (audioController.IsReleased)//可用?
            {
                return AddPlayingAudioList(audioController);
            }
            sourceCachePool.Enqueue(audioController);
        }
        return AddPlayingAudioList(CreatAudioController());
    }
    private void Lose(AudioController audioController)
    {
        if (playingAudio.Contains(audioController))
            playingAudio.Remove(audioController);

        if (audioController == null ||
            audioController.IsDestroyed)
            return;
        if (!sourceCachePool.Contains(audioController))
            sourceCachePool.Enqueue(audioController);
        audioController.SetDisable();
    }
    private AudioClip GetClip(string cname)
    {
        if (cname == null)
            return null;
        //存在
        if (audioClipPool.ContainsKey(cname) &&
            audioClipPool[cname] != null)
        {
            return audioClipPool[cname];
        }

        //创建成功
        if (CreatAudioClip(cname))
        {
            return audioClipPool[cname];
        }
        //创建失败
        return null;
    }

    private AudioClip[] GetClip(string[] names)
    {
        if (names == null)
            return null;
        //AudioClip[] audioClips = new AudioClip[names.Length];
        Queue audioClips = new Queue();
        AudioClip audioClip;
        for (int i = 0; i < names.Length; i++)
        {
            audioClip = GetClip(names[i]);
            if (audioClip != null)
                audioClips.Enqueue(GetClip(names[i]));
        }

        if (audioClips.Count == 0)
            return null;

        return audioClips.ToArray();
    }

    //private void Lose(AudioClip audioClip)
    //{
    //    audioClipPool.Remove(audioClip.name);
    //    Resources.UnloadAsset(audioClip);
    //}
    /// 
    /// 读取音频文件,改变读取方式可修改这里
    /// 
    /// 
    /// 是否读取成功
    private bool CreatAudioClip(string name)
    {
        AudioClip audioClip = Resources.Load(name);
        if (audioClip == null)
        {
            Debug.LogError("读取音频资源失败:" + name);
            return false;
        }

        if (audioClipPool.ContainsKey(name))
            audioClipPool[name] = audioClip;
        else
            audioClipPool.Add(name, audioClip);

        return true;
    }
    /// 
    /// 默认属性模板,改默认属性在这里
    /// 特性在AudioController.SetXXX()
    /// 
    /// 
    private AudioController CreatAudioController()
    {
        return new AudioController(this);
    }

    #endregion 缓存池

    /// 
    /// 保存必要信息,以及自主控制声音播放
    /// 若以后有多种行为可改为接口编程
    /// 
    [System.Serializable]
    private class AudioController
    {
        /// 
        /// 声音控制器ID
        /// 
        internal readonly int ID;
        /// 
        /// 目标声音源组建
        /// 
#if Sirenix_OdinInspector
        [SerializeField, ReadOnly, GUIColor("BGC")]
#elif UNITY_EDITOR
        [SerializeField]
#endif
        private AudioSource audioSource;


        /// 
        /// 是否正在播放,用于面板显示
        /// 
#if Sirenix_OdinInspector
#elif UNITY_EDITOR
        [SerializeField]
#endif
        private bool playing = false;
#if UNITY_EDITOR
        /// 
        /// 用于限制面板显示播放进度的最大值和最小值
        /// 
        private float maxProgress = 1;
        /// 
        /// 播放进度,用于面板显示
        /// 
#endif
#if Sirenix_OdinInspector
        private Color BGC { get { return playing ? Color.green : Color.red; } set { } }
        [SerializeField, ReadOnly, PropertyRange(0, "maxProgress"), GUIColor("BGC")]
        private float progress = 0;
#elif UNITY_EDITOR
        [SerializeField]
        private float progress = 0;
#endif

        /// 
        /// 当前音频片段结束时间
        /// 
        private float endTime;
        /// 
        /// 定时停止播放
        /// 
        private float stopTime = 0;
        /// 
        /// 待播音频
        /// 
        internal AudioClip[] audioClips { get; private set; }
        /// 
        /// 追随目标
        /// 
        private Transform target;
        /// 
        /// 坐标及偏移
        /// 
        private Vector3 pos;
        /// 
        /// 是否随机
        /// 
        private bool random = false;
        /// 
        /// 是否循环
        /// 
        private bool loop = false;
        /// 
        /// 为真这逐渐停止播放
        /// 
        private bool stoping = false;
        /// 
        /// 渐入渐出用的
        /// 
        private float volumescale = 0;

        #region AudioSource属性
        internal float minDistance
        {
            get { return audioSource.minDistance; }
            set { audioSource.minDistance = value; }
        }
        internal float maxDistance
        {
            get { return audioSource.maxDistance; }
            set { audioSource.maxDistance = value; }
        }
        internal float spatialBlend
        {
            get { return audioSource.spatialBlend; }
            set { audioSource.spatialBlend = value; }
        }
        internal float pitch
        {
            get { return audioSource.pitch; }
            set { audioSource.pitch = value; }
        }
        internal bool mute
        {
            get { return audioSource.mute; }
            set { audioSource.mute = value; }
        }
        #endregion AudioSource属性

        internal AudioController(AudioManager audioManager)
        {
            ID = audioManager.idPointer++;
            audioManager.AudioControllerDic.Add(ID, this);
            IsPlayFinished = false;
            IsDestroyed = false;
            audioSource = new GameObject("AudioPlayer").AddComponent();
            audioSource.transform.SetParent(instance.transform, false);
            audioSource.playOnAwake = false;
            audioSource.loop = false;
        }
        /// 
        /// 当前正在播放的几个音频
        /// 
        internal int CurrIdex { get; private set; }

        /// 
        /// 是否播放完成
        /// 
        internal bool IsPlayFinished { get; private set; }
        /// 
        /// 是否被销毁
        /// 
        internal bool IsDestroyed { get; private set; }
        /// 
        /// 是背景音乐还是音效
        /// 
        internal bool IsMusic { get; private set; }
        /// 
        /// 是否不再使用(不再播放,没有渐变,不需要再更新。可以重新利用了)
        /// 
        internal bool IsReleased { get; private set; }
        /// 
        /// 过渡时间
        /// 
        internal float TransitionTime { get; private set; }
        /// 
        /// 音量参数,不是实际音量,是传入的音量
        /// 
        internal float Volume { get; private set; }
        /// 
        /// 最小随机间隔
        /// 
        internal float MinInterval { get; private set; }
        /// 
        /// 最大随机间隔
        /// 
        internal float MaxInterval { get; private set; }
        /// 
        /// 开始播放的时间
        /// 
        internal float StartTime { get; private set; }

        /// 
        /// 播放背景音乐(背景音乐模板)
        /// 
        /// 
        /// 
        internal void SetMusic(float transitionTime, bool random, bool loop, params AudioClip[] audioClips)
        {
            //判断这些音频是否可用
            if (audioClips == null || audioClips.Length == 0 || audioClips[0] == null)
            {
                audioSource.Stop();
                IsPlayFinished = true;
                IsReleased = true;
                return;
            }

            //初始化数值
            stopTime = 0;
            IsPlayFinished = false;
            IsReleased = false;
            target = null;
            volumescale = 0;
            Volume = 1;
            StartTime = Time.realtimeSinceStartup;
            IsMusic = true;
            audioSource.loop = true;
            loop = true;
            stoping = false;
            pitch = 1;
            audioSource.spatialBlend = 0;
            audioSource.loop = true;
            pos = Vector3.zero;
            CurrIdex = 0;

#if UNITY_EDITOR
            //面板显示进度
            endTime = 0;
            for (int i = 0; i < audioClips.Length; i++)
            {
                if (audioClips[i] != null)
                {
                    endTime += audioClips[i].length;
                }
            }
#if Sirenix_OdinInspector
            maxProgress = endTime;
#endif
#endif
            //赋值
            TransitionTime = transitionTime;
            if (audioClips.Length > 1)
                this.random = random;
            else
                this.random = false;
            if (random)
                this.loop = true;
            else
                this.loop = loop;
            this.audioClips = audioClips;


            Play();
        }
        /// 
        /// 播放音效(音效模板)
        /// 
        /// 音效跟谁目标
        /// 偏移或世界坐标
        /// 2D或3D声音(0~1)
        /// 是否随机播放,若随机,则一定循环
        /// 音调
        /// 是否循环,若随机,则一定循环
        /// 音频文件
        internal void SetSound(Transform target, Vector3 pos, float space3d, bool random, float pitch, bool loop, float volume, params AudioClip[] audioClips)
        {
            //判断这些音频是否可用
            if (audioClips == null || audioClips.Length == 0 || audioClips[0] == null)
            {
                audioSource.Stop();
                IsPlayFinished = true;
                IsReleased = true;
                return;
            }

            //初始化数值
            SetInterval(0, 0);
            stopTime = 0;
            IsPlayFinished = false;
            IsReleased = false;
            volumescale = 0;
            stoping = false;
            TransitionTime = 0;
            IsMusic = false;
            CurrIdex = -1;
            StartTime = Time.realtimeSinceStartup;
            this.target = target;
            this.pos = pos;
            audioSource.loop = false;

#if UNITY_EDITOR
            //面板显示进度
            endTime = 0;
            for (int i = 0; i < audioClips.Length; i++)
            {
                if (audioClips[i] != null)
                {
                    endTime += audioClips[i].length;
                }
            }
#if Sirenix_OdinInspector
            maxProgress = endTime;
#endif
#endif
            //赋值
            this.audioClips = audioClips;

            if (audioClips.Length > 1)
                this.random = random;
            else
                this.random = false;
            if (random)
                this.loop = true;
            else
                this.loop = loop;

            this.pitch = pitch;
            audioSource.spatialBlend = space3d;
            Volume = volume;

            //位置信息
            if (target == null)
            {
                audioSource.transform.position = pos;
            }
            else
            {
                if (pos == Vector3.zero)
                {
                    this.pos = Vector3.zero;
                    audioSource.transform.position = target.position;
                }
                else
                {
                    this.pos = new Vector3(pos.x * target.lossyScale.x, pos.y * target.lossyScale.y, pos.z * target.lossyScale.z);
                    audioSource.transform.position = target.TransformPoint(this.pos);
                }
            }
        }
        /// 
        /// 播放多段音频时,设置随机间隔
        /// 
        /// 最小间隔
        /// 最大间隔
        internal void SetInterval(float minInterval, float maxInterval)
        {
            MinInterval = minInterval;
            MaxInterval = maxInterval;
        }
        /// 
        /// 重设audioClips
        /// 参数为空时不生效
        /// 
        /// 
        internal void SetAudioClips(params AudioClip[] audioClips)
        {
            if (audioClips == null || audioClips.Length == 0 || audioClips[0] == null)
                return;
            this.audioClips = audioClips;
        }
        /// 
        /// 如果后续添加其他模板
        /// (说好的对拓展开放,对修改关闭呢。。。这妥妥的相反)
        /// (有需要可以修改一下,把这些内容放到派生类,只是初值不同)
        /// 
        internal void SetOther()
        {
            //never use 警报
#if UNITY_EDITOR
            if (playing || progress == 0 || maxProgress == 0) { }
#endif
        }
        /// 
        /// 禁用,准备回收
        /// 
        internal void SetDisable()
        {
            audioClips = null;
            target = null;
            pos = Vector3.zero;
            IsReleased = true;
            if (audioSource != null)
            {
                //if (audioSource.transform != instance.transform)
                {
                    audioSource.Stop();
                    audioSource.transform.SetParent(instance.transform);
                    audioSource.transform.localPosition = Vector3.zero;
                    audioSource.gameObject.SetActive(false);
                    return;
                }
                //audioSource.enabled = false;
            }
        }
        internal void OnUpdate(float deltaTime)
        {
            //检查是否可用,不可用标记销毁
            if (!IsValid())
            {
                IsDestroyed = true;
                Release();
                playing = false;
                return;
            }

#if UNITY_EDITOR
            //面板显示进度
            progress = Time.realtimeSinceStartup - StartTime;
            if (random)
            {
                progress = audioSource.time;
            }
            if (random || stopTime > 0)
            {
                if (progress > maxProgress)
                {
                    progress = maxProgress;
                }
            }
            else if (loop)
            {
                progress = audioSource.time;
                if (progress > maxProgress)
                {
                    progress -= maxProgress;
                }
            }

#if !Sirenix_OdinInspector
            progress /= maxProgress;
#endif

#endif
            //跟随目标移动,而不作为目标的子物体,防止随目标一起销毁
            if (target != null)
            {
                if (pos == Vector3.zero)
                {
                    audioSource.transform.position = target.position;
                }
                else
                {
                    audioSource.transform.position = target.TransformPoint(pos);
                }
            }

            //渐出
            if (stoping)
            {
                if (TransitionTime == 0 ||
                    volumescale <= 0)
                {
                    volumescale = 0;
                    audioSource.volume = 0;
                    IsPlayFinished = true;
                    return;
                }
                audioSource.volume = Volume * (IsMusic ? instance.MusicVolume : instance.SoundVolume) * volumescale;
                volumescale -= deltaTime / TransitionTime;
                return;
            }

            //定时停止播放
            if (stopTime > 0 && Time.time > stopTime)
            {
                Stop(TransitionTime, false);
            }

            //音量过渡
            if (TransitionTime == 0 ||
                volumescale >= 1)
            {
                volumescale = 1;
            }
            else
            {
                volumescale += deltaTime / TransitionTime;
            }
            audioSource.volume = Volume * (IsMusic ? instance.MusicVolume : instance.SoundVolume) * volumescale;

            //播放完成不需要切换音频
            if (IsPlayFinished || (IsMusic && loop))
                return;

            //检查播放进度,播放下一个音频,或标记为播放完成
            //暂时没有排除audioClips数组中有空指针的情况
            if (Time.realtimeSinceStartup >= endTime)
            {
                if (random)//随机顺序
                {
                    CurrIdex = Random.Range(0, audioClips.Length);
                    Play();
                    return;
                }
                CurrIdex++;
                if (CurrIdex < audioClips.Length)//顺序
                {
                    Play();
                    return;
                }
                if (loop)//顺序循环
                {
                    CurrIdex = 0;
                    Play();
                    return;
                }
                //顺序不循环==完成播放
                IsPlayFinished = true;
                playing = false;
            }
        }
        /// 
        /// 播放
        /// 
        private void Play()
        {
            if (CurrIdex >= audioClips.Length || audioClips[CurrIdex] == null)
            {
                //audioSource.Stop();
                return;
            }

            playing = true;
            audioSource.gameObject.SetActive(true);
            audioSource.clip = audioClips[CurrIdex];
            if (MinInterval == MaxInterval)
            {
                endTime = Time.realtimeSinceStartup + audioClips[CurrIdex].length + MinInterval;
            }
            else
            {
                endTime = Time.realtimeSinceStartup + audioClips[CurrIdex].length + Random.Range(MinInterval, MaxInterval);
            }
            audioSource.Play();
#if Sirenix_OdinInspector
            //面板显示进度
            if (stopTime <= 0)
            {
                if (random)
                {
                    maxProgress = audioClips[CurrIdex].length;
                }
            }
#elif UNITY_EDITOR
            maxProgress = 1;
#endif
        }
        /// 
        /// 停止播放
        /// 
        /// 渐出时间
        /// 是否等待播放完成,若等待完成则没有渐出效果
        internal void Stop(float transitionTime, bool waitFinished)
        {
            playing = false;
            TransitionTime = transitionTime;
            if (waitFinished)
            {
                CurrIdex = audioClips.Length;
                audioSource.loop = false;
                endTime = Time.realtimeSinceStartup + (audioSource.clip.length - audioSource.time % audioSource.clip.length);
                loop = false;
            }
            else
            {
                stoping = true;
            }
        }
        /// 
        /// 设置剩余长度
        /// 
        /// 
        internal void SetRemainingLength(float l, float transitionTime)
        {
            TransitionTime = transitionTime;
            stopTime = Time.time + l;
#if Sirenix_OdinInspector
            maxProgress = Time.realtimeSinceStartup + l - StartTime;
#endif
            loop = true;
        }
        /// 
        /// 检查是否有效
        /// 
        /// 
        private bool IsValid()
        {
            if (IsDestroyed)
                return false;
            if (audioSource == null)
                return false;
            return true;
        }
        /// 
        /// 释放资源,准备销毁
        /// 
        internal void Release()
        {
            playing = false;
            IsDestroyed = true;
            if (audioSource != null /*&&
                audioSource.transform != instance.transform*/)
            {
                Destroy(audioSource.gameObject);
            }
            if (instance.AudioControllerDic.ContainsKey(ID))
                instance.AudioControllerDic.Remove(ID);
            target = null;
            audioClips = null;
        }
        /// 
        /// 是否正在播放
        /// 
        /// 
        internal bool IsPlaying()
        {
            return !IsDestroyed &&
                   !stoping &&
                   !IsPlayFinished &&
                   audioSource.isPlaying;
        }
        /// 
        /// 是否正在播放某段音频
        /// 
        /// 
        /// 
        internal bool IsPlaying(string clipName)
        {
            return !IsDestroyed &&
                   !stoping &&
                   !IsPlayFinished &&
                   clipName.EndsWith(audioSource.clip.name) &&
                   audioSource.isPlaying;
        }
    }

    #endregion 私有成员
}


 

你可能感兴趣的:(Unity)