国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

自定義Unity組件——AudioManager(音頻管理器)

這篇具有很好參考價(jià)值的文章主要介紹了自定義Unity組件——AudioManager(音頻管理器)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

需求描述

? ? ? ? 在游戲開發(fā)中,音頻資源是不可或缺的,通常情況下音頻資源隨機(jī)分布,各個(gè)音頻的操作和管理都是各自負(fù)責(zé),同時(shí)對(duì)于音頻的很多操作邏輯都是大同小異的,這就造成了許多冗余代碼的堆疊,除此之外在獲取各類音頻資源的時(shí)候也會(huì)造成不必要的開銷。所以解決資源分散的問題最直接的方式就是集中管理和分配,通過統(tǒng)一的渠道和特有標(biāo)識(shí)即可獲取或操作對(duì)應(yīng)的音頻資源。所以本篇文章將圍繞這個(gè)方案進(jìn)行嘗試。

功能描述

? ? ? ? 在Unity中我們導(dǎo)入的音頻資源都會(huì)轉(zhuǎn)換為AudioClip,音頻的設(shè)置和管理則由AudioSource負(fù)責(zé),AudioListener負(fù)責(zé)監(jiān)聽音頻。我們可以在此基礎(chǔ)上去封裝,從而打造一個(gè)音頻管理器。

????????音頻管理器負(fù)責(zé)管理音頻信息以及操作音頻,比如音頻信息的增加和刪除,音頻的播放和暫停等;

????????音頻信息可以使用一個(gè)單獨(dú)的實(shí)體類來記錄,用于記錄AudioSource組件中的信息,之所以單獨(dú)用一個(gè)實(shí)體類來記錄音頻信息而不直接采用AudioSource,主要是可以通過業(yè)務(wù)需求去動(dòng)態(tài)調(diào)整所要記錄的音頻信息,我們的實(shí)際開發(fā)中并非需要AudioSource中所有的信息,有時(shí)候僅僅需要其中的一部分,同時(shí)音頻信息可能涉及存儲(chǔ),直接采用AudioSource可能無法與已經(jīng)開發(fā)好的存儲(chǔ)系統(tǒng)相互兼容,而實(shí)體類可以為其添加接口或繼承來兼容存儲(chǔ)系統(tǒng);

????????AudioSource組件的管理可以通過一個(gè)組件池進(jìn)行管理,我們知道AudioSource也是等同于一個(gè)音頻實(shí)體類,但是其同時(shí)也是一種組件,組件同樣作為一種資源,通常情況下相比簡(jiǎn)單的實(shí)體類而言會(huì)帶來更大的開銷,例如一個(gè)場(chǎng)景中有十個(gè)游戲?qū)ο笥胁シ乓纛l的需求,那么按照傳統(tǒng)情況就需要每個(gè)游戲?qū)ο髵燧d一個(gè)AudioSource組件,但是實(shí)際運(yùn)行中十個(gè)游戲?qū)ο蟛⒉灰欢ㄐ枰瑫r(shí)播放音頻,它們或許都存在各自觸發(fā)音頻播放的條件,我們只需要在游戲?qū)ο笮枰シ乓纛l時(shí)為其分配一個(gè)AudioSource組件即可,組件池則負(fù)責(zé)維護(hù)AudioSource組件的生產(chǎn)、獲取和歸還,進(jìn)而減少資源開銷。

? ? ? ? 本質(zhì)上,AudioSource組件承擔(dān)的工作就是記錄音頻信息和操作音頻,我們現(xiàn)在將記錄工作分擔(dān)給音頻信息實(shí)體類,而操作音頻的工作則分擔(dān)給音頻管理器,例如音頻管理器的播放依舊是調(diào)用AudioSource的播放方法,在播放之前由音頻管理器去獲取AudioSource組件并且為之配置音頻信息,其它的音頻操作邏輯同理。

代碼展示(C#)

AudioManager.cs

using System.Linq;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace Tools.AudioManagerAPI
{
    /// <summary>
    /// 音頻管理器
    /// </summary>
    [DisallowMultipleComponent]
    public class AudioManager : MonoBehaviour
    {
        [Header("必要屬性")]
        [Tooltip("音頻總音量,默認(rèn)為1(值屬于[0,1]),該值將影響所有音頻的音量,例如該值為0則所有音頻音量變?yōu)樵幸袅康?%,若為1則所有音頻音量保持不變,即該值將基于所有音頻的當(dāng)前音量進(jìn)行影響,而不是直接統(tǒng)一所有音頻的音量為該值")]
        [Range(0, 1), SerializeField] private float TotalVolume = 1;

        /// <summary>
        /// 音頻總音量,默認(rèn)為1(值屬于[0,1])
        /// <para>聲明:該值將影響所有音頻的音量,例如該值為0則所有音頻音量變?yōu)樵幸袅康?%,若為1則所有音頻音量保持不變,即該值將基于所有音頻的當(dāng)前音量進(jìn)行影響,而不是直接統(tǒng)一所有音頻的音量為該值</para>
        /// </summary>
        public float mTotalVolume
        {
            get { return TotalVolume; }
            set
            {
                if (value >= 0 && value <= 1 && TotalVolume != value)
                {
                    TotalVolume = value;
                    mTotalVolumeChangedEvents?.Invoke(value);
                }
            }
        }

        /// <summary>
        /// 是否啟用音頻信息覆蓋,默認(rèn)為true
        /// </summary>
        public bool mIsOverWrite { get => isOverWrite; set => isOverWrite = value; }

        /// <summary>
        /// 音頻管理器中所存儲(chǔ)的音頻數(shù)量
        /// </summary>
        public int mCount { get => audioInfos.Count; }

        /// <summary>
        /// 總音量更改事件回調(diào)
        /// </summary>
        public event Action<float> mTotalVolumeChangedEvents;

        /// <summary>
        /// 音頻信息名稱合集
        /// </summary>
        public string[] mAudioInfoNames { get => audioInfos.Keys.ToArray(); }

        private Dictionary<string, AudioInfo> audioInfos;//音頻信息集合
        private bool isInit;//是否完成了初始化
        private bool isOverWrite;//是否啟用音頻信息覆蓋
        private static AudioSourcePool audioSourcePool = AudioSourcePool.GetInstance();//AudioSource組件池

        /// <summary>
        /// 播放指定名稱的音頻
        /// <para>p_audioName:音頻名稱</para>
        /// </summary>
        public void Play(string p_audioName)
        {
            if (isInit)
            {
                if (audioInfos.ContainsKey(p_audioName))
                {
                    AudioInfo ai = audioInfos[p_audioName];
                    AudioSource v_audioSource = audioSourcePool.Get(ai);
                    ai.mAudioSource = v_audioSource;
                    ai.Play();
                }
            }
        }

        /// <summary>
        /// 播放指定名稱的音頻并開啟立體聲過渡
        /// <para>p_audioName:音頻名稱</para>
        /// <para>聲明:該方法要求已啟用立體聲過渡且已設(shè)置好立體聲過渡的相關(guān)屬性</para>
        /// </summary>
        public void PlayWithStereoTransition(string p_audioName)
        {
            if (isInit)
            {
                if (audioInfos.ContainsKey(p_audioName))
                {
                    AudioInfo ai = audioInfos[p_audioName];
                    AudioSource v_audioSource = audioSourcePool.Get(ai);
                    ai.mAudioSource = v_audioSource;
                    StartCoroutine(ai.mStereoPanTransitionCoroutine);
                    ai.Play();
                }
            }
        }

        /// <summary>
        /// 播放指定名稱的音頻并開啟立體聲過渡
        /// <para>p_audioName:音頻名稱</para>
        /// <para>p_stereoTransitionValues:立體聲過渡值集合</para>
        /// <para>p_stereoTimeSpan:立體聲過渡每幀時(shí)間間隔</para>
        /// </summary>
        public void PlayWithStereoTransition(string p_audioName, float[] p_stereoTransitionValues, float p_stereoTimeSpan)
        {
            if (isInit)
            {
                if (audioInfos.ContainsKey(p_audioName))
                {
                    AudioInfo ai = audioInfos[p_audioName];
                    AudioSource v_audioSource = audioSourcePool.Get(ai);
                    ai.mAudioSource = v_audioSource;
                    ai.mStereoTransition = true;
                    ai.mStereoTransitionValues = p_stereoTransitionValues;
                    ai.mStereoTransitionTimeSpan = p_stereoTimeSpan;
                    StartCoroutine(ai.mStereoPanTransitionCoroutine);
                    ai.Play();
                }
            }
        }

        /// <summary>
        /// 暫停播放指定名稱的音頻
        /// <para>p_audioName:音頻名稱</para>
        /// </summary>
        public void Pause(string p_audioName)
        {
            if (isInit)
            {
                if (audioInfos.ContainsKey(p_audioName))
                {
                    AudioInfo ai = audioInfos[p_audioName];
                    StopCoroutine(ai.mStereoPanTransitionCoroutine);
                    ai.Pause();
                    audioSourcePool.Return(ai.mAudioSource);
                }
            }
        }

        /// <summary>
        /// 添加音頻信息
        /// <para>p_audioInfo:音頻信息</para>
        /// <para>聲明1:若啟用了音頻信息覆蓋,當(dāng)存在相同名稱的音頻時(shí),新的音頻信息將覆蓋舊的音頻信息</para>
        /// <para>聲明2:默認(rèn)啟用了音頻信息覆蓋,可通過mIsOverWrite屬性設(shè)置禁用</para>
        /// </summary>
        public void AddAudioInfo(AudioInfo p_audioInfo)
        {
            if (isInit) DoAddAudioInfo(p_audioInfo);
        }

        /// <summary>
        /// 刪除音頻信息
        /// <para>p_audioName:音頻名稱</para>
        /// <para>返回值:若刪除成功則返回true,否則返回false</para>
        /// </summary>
        public bool DeleteAudioInfo(string p_audioName)
        {
            if (isInit) return DoDeleteAudioInfo(p_audioName);
            return false;
        }

        private void Awake()
        {
            isInit = false;
            if (InitParameters()) isInit = true;
        }

        //添加音頻信息的執(zhí)行邏輯
        private void DoAddAudioInfo(AudioInfo p_audioInfo)
        {
            if (p_audioInfo != null && !String.IsNullOrEmpty(p_audioInfo.mAudioName))
            {
                string v_audioName = p_audioInfo.mAudioName;
                p_audioInfo.BindAudioManager(this);
                if (isOverWrite) audioInfos[v_audioName] = p_audioInfo;
                else if (!audioInfos.ContainsKey(v_audioName)) audioInfos.Add(v_audioName, p_audioInfo);
            }
        }

        //刪除音頻信息的執(zhí)行邏輯
        private bool DoDeleteAudioInfo(string p_audioName)
        {
            if (!String.IsNullOrEmpty(p_audioName) && audioInfos.ContainsKey(p_audioName))
            {
                audioInfos[p_audioName].BindAudioManager(null);
                return audioInfos.Remove(p_audioName);
            }
            return false;
        }

        //對(duì)音頻管理器相關(guān)參數(shù)進(jìn)行初始化
        private bool InitParameters()
        {
            audioInfos = new Dictionary<string, AudioInfo>();
            isOverWrite = true;
            audioSourcePool.BindAudioManager(this);
#if UNITY_EDITOR
            foreach (AudioInfo ai in AudioInfos)
                DoAddAudioInfo(ai);
#endif
            return true;
        }

#if UNITY_EDITOR
        /// <summary>
        /// 在當(dāng)前Inspector面板中的AudioInfos中的元素?cái)?shù)量
        /// </summary>
        public int mAudioInfoCount { get => AudioInfos?.Length > 0 ? AudioInfos.Length : 0; }

        [SerializeField] private AudioInfo[] AudioInfos;//存儲(chǔ)Inspector面板中

        /// <summary>
        /// 在當(dāng)前Inspector面板中的AudioInfos中添加一個(gè)元素
        /// </summary>
        public void Add()
        {
            AudioInfo v_audioInfo = new AudioInfo();
            if (AudioInfos?.Length > 0)
            {
                AudioInfo[] v_audioInfos = new AudioInfo[AudioInfos.Length + 1];
                AudioInfos.CopyTo(v_audioInfos, 0);
                v_audioInfos[v_audioInfos.Length - 1] = v_audioInfo;
                AudioInfos = new AudioInfo[v_audioInfos.Length];
                v_audioInfos.CopyTo(AudioInfos, 0);
            }
            else AudioInfos = new AudioInfo[] { v_audioInfo };
            v_audioInfo.ValidateCheck();
        }

        /// <summary>
        /// 在當(dāng)前Inspector面板中的AudioInfos中刪除一個(gè)元素
        /// </summary>
        public void Delete(int p_index)
        {
            if (AudioInfos?.Length == 1) AudioInfos = Array.Empty<AudioInfo>();
            else if (AudioInfos?.Length > 1)
            {
                AudioInfo[] v_audioInfos = new AudioInfo[AudioInfos.Length - 1];
                int v_index = 0;
                for (int i = 0; i < AudioInfos.Length; i++)
                {
                    if (i != p_index) v_audioInfos[v_index++] = AudioInfos[i];
                }
                AudioInfos = new AudioInfo[v_audioInfos.Length];
                v_audioInfos.CopyTo(AudioInfos, 0);
            }
        }

        private void OnValidate()
        {
            foreach (AudioInfo audioInfo in AudioInfos)
            {
                audioInfo?.ValidateCheck();
            }
        }
#endif
    }
}

AudioInfo.cs

using UnityEngine;
using System.Collections;
using System.Linq;
using System;

namespace Tools.AudioManagerAPI
{
    /// <summary>
    /// 音頻信息
    /// </summary>
    [System.Serializable]
    public class AudioInfo
    {
        [Header("必要組件")]
        [Tooltip("AudioClip組件"), SerializeField] private AudioClip TheAudioClip;

        [Header("必要屬性")]
        [Tooltip("音頻名稱"), SerializeField] private string AudioName;
        [Tooltip("音頻音量,默認(rèn)為1(值屬于[0,1])"), Range(0, 1), SerializeField] private float Volume = 1;
        [Tooltip("音頻播放速度,默認(rèn)為1(值屬于[-3,3])"), Range(-3, 3), SerializeField] private float Pitch = 1;
        [Tooltip("立體聲位置,默認(rèn)為0(值屬于[-1,1]),若為-1則完全為左聲道,若為1則完全為右聲道"), Range(-1, 1), SerializeField] private float StereoPan = 0;
        [Tooltip("音頻優(yōu)先級(jí),默認(rèn)為128(值屬于[0,256])"), Range(0, 256), SerializeField] private int Priority = 128;
        [Tooltip("是否在場(chǎng)景啟動(dòng)時(shí)進(jìn)行播放,默認(rèn)為true"), SerializeField] private bool PlayOnAwake = true;
        [Tooltip("是否循環(huán)播放,默認(rèn)為false"), SerializeField] private bool Loop;
        [Tooltip("是否忽略總音量影響,默認(rèn)為false"), SerializeField] private bool IgnoreTotalVolume;

        [Header("立體聲過渡屬性")]
        [Tooltip("是否啟用立體聲過渡,默認(rèn)為false"), SerializeField] private bool StereoTransition;
        [Tooltip("立體聲過渡的每幀時(shí)間間隔,默認(rèn)為0.5(值屬于[0.1,5])"), Range(.1f, 5), SerializeField] private float StereoTransitionTimeSpan = 0.5f;
        [Tooltip("立體聲過渡值集合"), SerializeField] private float[] StereoTransitionValues;

        /// <summary>
        /// 音頻名稱
        /// </summary>
        public string mAudioName { get => AudioName; set => AudioName = value; }

        /// <summary>
        /// 音頻音量,默認(rèn)為1(值屬于[0,1])
        /// </summary>
        public float mVolume
        {
            get { return Volume; }
            set { if (value >= 0 && value <= 1) Volume = value; }
        }

        /// <summary>
        /// 音頻播放速度,默認(rèn)為1(值屬于[-3,3])
        /// </summary>
        public float mPitch
        {
            get { return Pitch; }
            set { if (value >= -3 && value <= 3) Pitch = value; }
        }

        /// <summary>
        /// 立體聲位置,默認(rèn)為0(值屬于[-1,1]),若為-1則完全為左聲道,若為1則完全為右聲道
        /// </summary>
        public float mStereoPan
        {
            get { return StereoPan; }
            set { if (value >= -1 && value <= 1) StereoPan = value; }
        }

        /// <summary>
        /// 音頻優(yōu)先級(jí),默認(rèn)為128(值屬于[0,256])
        /// </summary>
        public int mPriority
        {
            get { return Priority; }
            set { if (value >= 0 && value <= 256) Priority = value; }
        }

        /// <summary>
        /// 是否在場(chǎng)景啟動(dòng)時(shí)進(jìn)行播放,默認(rèn)為true
        /// </summary>
        public bool mPlayOnAwake { get => PlayOnAwake; set => PlayOnAwake = value; }

        /// <summary>
        /// 是否循環(huán)播放,默認(rèn)為false
        /// </summary>
        public bool mLoop { get => Loop; set => Loop = value; }

        /// <summary>
        /// 是否啟用立體聲過渡,默認(rèn)為false
        /// </summary>
        public bool mStereoTransition { get => StereoTransition; set => StereoTransition = value; }

        /// <summary>
        /// 立體聲過渡的每幀時(shí)間間隔,默認(rèn)為0.5(值屬于[0.1,5])
        /// </summary>
        public float mStereoTransitionTimeSpan
        {
            get { return StereoTransitionTimeSpan; }
            set { if (value >= 0.1f && value <= 5) StereoTransitionTimeSpan = value; }
        }

        /// <summary>
        /// 立體聲過渡值集合
        /// </summary>
        public float[] mStereoTransitionValues
        {
            get => StereoTransitionValues;
            set => StereoTransitionValues = value;
        }

        /// <summary>
        /// AudioSource組件
        /// </summary>
        public AudioSource mAudioSource { get => audioSource; set => audioSource = value; }

        /// <summary>
        /// 立體聲過渡協(xié)程
        /// </summary>
        public IEnumerator mStereoPanTransitionCoroutine { get => stereoPanTransitionCoroutine; }

        /// <summary>
        /// 是否忽略總音量影響,默認(rèn)為false
        /// </summary>
        public bool mIgnoreTotalVolume { get => IgnoreTotalVolume; set => IgnoreTotalVolume = value; }

        private AudioSource audioSource;//AudioSource組件
        private AudioManager audioManager;//音頻管理器
        private bool isInit;//是否完成初始化
        private IEnumerator stereoPanTransitionCoroutine;//立體聲過渡協(xié)程
        private float actualVolume;//實(shí)際音量
        private Action<float> totalVolumeChangedEvent;//總音量更改事件對(duì)象

        /// <summary>
        /// 將指定的AudioSource組件信息記錄在新的AudioInfo實(shí)例中并返回它
        /// <para>p_audioSource:指定的AudioSource組件</para>
        /// <para>返回值:新的AudioInfo實(shí)例</para>
        /// </summary>
        public static AudioInfo Record(AudioSource p_audioSource)
        {
            AudioInfo v_audioInfo = new AudioInfo();
            if (p_audioSource != null)
            {
                v_audioInfo.TheAudioClip = p_audioSource.clip;
                v_audioInfo.Volume = p_audioSource.volume;
                v_audioInfo.Pitch = p_audioSource.pitch;
                v_audioInfo.StereoPan = p_audioSource.panStereo;
                v_audioInfo.Priority = p_audioSource.priority;
                v_audioInfo.PlayOnAwake = p_audioSource.playOnAwake;
                v_audioInfo.Loop = p_audioSource.loop;
                v_audioInfo.audioSource = p_audioSource;
            }
            return v_audioInfo;
        }

        public AudioInfo()
        {
            isInit = false;
            InitToDefault();
        }

        /// <summary>
        /// 播放音頻
        /// </summary>
        public void Play()
        {
            if (audioSource != null && !audioSource.isPlaying)
            {
                if (!IgnoreTotalVolume)
                {
                    if (actualVolume < 0 || actualVolume > 1) actualVolume = Volume;
                    audioSource.volume = actualVolume;
                }
                else actualVolume = -1;
                audioSource.Play();
            }
        }

        /// <summary>
        /// 暫停音頻播放
        /// </summary>
        public void Pause()
        {
            if (audioSource != null && audioSource.isPlaying)
            {
                audioSource.Pause();
                audioSource.volume = Volume;
            }
        }

        /// <summary>
        /// 綁定音頻管理器
        /// <para>p_audioManager:音頻管理器</para>
        /// <para>聲明1:若有需要可通過該方法將當(dāng)前的AudioInfo與指定的音頻管理器進(jìn)行綁定</para>
        /// <para>聲明2:綁定后將自動(dòng)向指定的音頻管理器添加當(dāng)前的AudioInfo</para>
        /// </summary>
        public void BindAudioManager(AudioManager p_audioManager)
        {
            audioManager = p_audioManager;
            if (audioManager != null)
            {
                audioManager.mTotalVolumeChangedEvents -= totalVolumeChangedEvent;
                audioManager.mTotalVolumeChangedEvents += totalVolumeChangedEvent;
            }
        }

        /// <summary>
        /// 初始化為默認(rèn)值
        /// </summary>
        public void InitToDefault()
        {
            if (!isInit)
            {
                TheAudioClip = null;
                AudioName = "Audio";
                Volume = 1;
                Pitch = 1;
                StereoPan = 0;
                StereoTransitionValues = null;
                StereoTransitionTimeSpan = 0.5f;
                Priority = 128;
                StereoTransition = false;
                PlayOnAwake = true;
                Loop = false;
                audioSource = null;
                stereoPanTransitionCoroutine = StereoPanTransition();
                totalVolumeChangedEvent = (val) => TotalVolumeChangedEvent(val);
                actualVolume = -1;
            }
        }

        /// <summary>
        /// 將當(dāng)前AudioInfo實(shí)例中的信息配置給指定的AudioSource組件
        /// <para>p_audioSource:指定的AudioSource組件</para>
        /// </summary>
        public void ShareTo(AudioSource p_audioSource)
        {
            if (p_audioSource != null)
            {
                p_audioSource.clip = TheAudioClip;
                p_audioSource.volume = Volume;
                p_audioSource.pitch = Pitch;
                p_audioSource.panStereo = StereoPan;
                p_audioSource.priority = Priority;
                p_audioSource.playOnAwake = PlayOnAwake;
                p_audioSource.loop = Loop;
            }
        }

        /// <summary>
        /// 將指定的AudioSource組件信息存儲(chǔ)在當(dāng)前AudioInfo實(shí)例中
        /// <para>p_audioSource:指定的AudioSource組件</para>
        /// </summary>
        public void SelfRecord(AudioSource p_audioSource)
        {
            if (p_audioSource != null)
            {
                TheAudioClip = p_audioSource.clip;
                Volume = p_audioSource.volume;
                Pitch = p_audioSource.pitch;
                StereoPan = p_audioSource.panStereo;
                Priority = p_audioSource.priority;
                PlayOnAwake = p_audioSource.playOnAwake;
                Loop = p_audioSource.loop;
                audioSource = p_audioSource;
            }
        }

        // 總音量更改事件
        // p_totalVolume:總音量
        // 若不忽略總音量影響,通過調(diào)用該事件將基于總音量和當(dāng)前音量換算實(shí)際音量數(shù)值
        // 當(dāng)TotleVolume為0時(shí),實(shí)際音量為0;
        // 當(dāng)TotleVolume為1或不屬于[0,1)時(shí),實(shí)際音量為Volume;
        // 當(dāng)TotleVolume屬于(0,1)時(shí),實(shí)際音量為Volume * TotalVolume
        private void TotalVolumeChangedEvent(float p_totalVolume)
        {
            if (!IgnoreTotalVolume)
            {
                if (p_totalVolume == 0) actualVolume = 0;
                else if (p_totalVolume > 0 && p_totalVolume < 1) actualVolume = Volume * p_totalVolume;
                else actualVolume = Volume;
                //運(yùn)行時(shí)修改AudioSource音量
                if (audioSource != null) audioSource.volume = actualVolume;
            }
            else actualVolume = -1;
        }

        //立體聲過渡協(xié)程
        private IEnumerator StereoPanTransition()
        {
            int currentIndex = 0;
            while (true)
            {
                if (audioSource == null || !StereoTransition || StereoTransitionValues == null || StereoTransitionValues.Length == 0)
                    yield break;
                audioSource.panStereo = StereoTransitionValues[currentIndex];
                yield return new WaitForSeconds(StereoTransitionTimeSpan);
                currentIndex = (currentIndex + 1) % StereoTransitionValues.Length;
                if (currentIndex == 0) StereoTransitionValues = StereoTransitionValues.Reverse().ToArray<float>();
            }
        }

#if UNITY_EDITOR
        [NonSerialized] private bool isAudioClipLog;
        private bool isAudioNameLog;

        /// <summary>
        /// Inspector面板的數(shù)據(jù)更改檢測(cè)
        /// </summary>
        public void ValidateCheck()
        {
            AudioClipCheck();
            AudioNameCheck();
        }

        //AudioClip檢測(cè)
        private void AudioClipCheck()
        {
            if (TheAudioClip == null)
            {
                if (!isAudioClipLog)
                {
                    Debug.LogWarning("Component: <b><color=orange>TheAudioClip</color></b> is null.");
                    isAudioClipLog = true;
                }
            }
            else isAudioClipLog = false;
        }

        //AudioName檢測(cè)
        private void AudioNameCheck()
        {
            if (String.IsNullOrEmpty(AudioName))
            {
                if (!isAudioNameLog)
                {
                    Debug.LogWarning("Property: <b><color=orange>AudioName</color></b> is empty.");
                    isAudioNameLog = true;
                }
            }
            else isAudioNameLog = false;
        }
#endif
    }
}

AudioSourcePool.cs?

using System.Collections.Generic;
using UnityEngine;

namespace Tools.AudioManagerAPI
{
    /// <summary>
    /// AudioSource組件池
    /// </summary>
    public class AudioSourcePool
    {
        /// <summary>
        /// 空閑的AudioSource數(shù)量
        /// </summary>
        public int mFreeCount { get => audioSources.Count; }
        private Stack<AudioSource> audioSources;//AudioSource組件集合
        private AudioManager audioManager;//AudioManager組件
        private AudioInfo defaultAudioInfo;//默認(rèn)的AudioInfo

        /// <summary>
        /// 獲取實(shí)例(單例模式)
        /// </summary>
        public static AudioSourcePool GetInstance()
        {
            return Handler.instance;
        }

        /// <summary>
        /// 綁定音頻管理器
        /// <para>p_audioManager:音頻管理器</para>
        /// </summary>
        public void BindAudioManager(AudioManager p_audioManager)
        {
            if (p_audioManager != null) audioManager = p_audioManager;
        }

        /// <summary>
        /// 獲取AudioSource組件
        /// <para>返回值:AudioSource組件</para>
        /// </summary>
        public AudioSource Get()
        {
            return DoGet();
        }

        /// <summary>
        /// 獲取AudioSource組件并按照指定的AudioInfo為之配置屬性
        /// <para>p_audioInfo:指定的AudioInfo</para>
        /// <para>返回值:AudioSource組件</para>
        /// </summary>
        public AudioSource Get(AudioInfo p_audioInfo)
        {
            AudioSource v_audioSource = DoGet();
            p_audioInfo?.ShareTo(v_audioSource);
            return v_audioSource;
        }

        /// <summary>
        /// 歸還指定的AudioSource組件
        /// <para>p_audioSource:指定的AudioSource組件</para>
        /// </summary>
        public void Return(AudioSource p_audioSource)
        {
            if (p_audioSource != null)
            {
                CleanAudioSource(p_audioSource);
                audioSources.Push(p_audioSource);
            }
        }

        class Handler
        {
            public static AudioSourcePool instance = new AudioSourcePool();
        }

        private AudioSourcePool()
        {
            audioSources = new Stack<AudioSource>();
            defaultAudioInfo = new AudioInfo();
        }

        //獲取AudioSource組件的執(zhí)行邏輯
        private AudioSource DoGet()
        {
            if (audioManager == null) return null;
            AudioSource v_audioSource = null;
            while (v_audioSource == null)
            {
                if (audioSources.Count == 0) GenerateAudioSource();
                v_audioSource = audioSources.Pop();
            }
            return v_audioSource;
        }

        //生成AudioSource組件
        private void GenerateAudioSource()
        {
            if (audioManager?.gameObject != null)
            {
                AudioSource v_audioSource = audioManager.gameObject.AddComponent<AudioSource>();
                audioSources.Push(v_audioSource);
            }
        }

        //清洗AudioSource組件
        private void CleanAudioSource(AudioSource p_audioSource)
        {
            defaultAudioInfo.ShareTo(p_audioSource);
        }
    }
}

NumberRange.cs

using System.Collections.Generic;
using System.Linq;

namespace Tools.AudioManagerAPI
{
    /// <summary>
    /// 數(shù)值范圍數(shù)組工具類
    /// </summary>
    public static class NumberRange
    {
        /// <summary>
        /// 獲取指定范圍內(nèi)指定步長(zhǎng)的Float數(shù)值數(shù)組
        /// <para>p_start:起始值</para>
        /// <para>p_end:終點(diǎn)值</para>
        /// <para>p_step:步長(zhǎng)值</para>
        /// <para>[ContainsEnd]:是否包括終點(diǎn)值,默認(rèn)為false</para>
        /// <para>返回值:Float[]</para>
        /// </summary>
        public static float[] FloatRange(float p_start, float p_end, float p_step, bool ContainsEnd = false)
        {
            if (!ContainsEnd) return DoFloatRange(p_start, p_end, p_step).ToArray();
            else
            {
                List<float> result = DoFloatRange(p_start, p_end, p_step).ToList();
                result.Add(p_end);
                return result.ToArray();
            }
        }

        //獲取指定范圍內(nèi)指定步長(zhǎng)的Float數(shù)值數(shù)組的執(zhí)行邏輯
        static IEnumerable<float> DoFloatRange(float p_start, float p_end, float p_step)
        {
            for (float i = p_start; i <= p_end; i += p_step)
            {
                yield return i;
            }
        }
    }
}

界面展示

audiomanager,Unity開發(fā),unity,音頻

演示效果

自定義Unity組件AudioManager

資源下載

GitHub_AudioManager? ??百度網(wǎng)盤

如果這篇文章對(duì)你有幫助,請(qǐng)給作者點(diǎn)個(gè)贊吧!?文章來源地址http://www.zghlxwxcb.cn/news/detail-767013.html

到了這里,關(guān)于自定義Unity組件——AudioManager(音頻管理器)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Unity基礎(chǔ) 音頻組件以及音頻播放

    Unity基礎(chǔ) 音頻組件以及音頻播放

    在游戲開發(fā)中,聲音是一個(gè)重要的環(huán)節(jié)。Unity中的聲音組件可以幫助開發(fā)者輕松地控制游戲中音頻的播放、音量、循環(huán)等屬性,從而實(shí)現(xiàn)更好的游戲體驗(yàn)。本文將詳細(xì)介紹Unity聲音組件的相關(guān)概念和技術(shù),以及其在游戲、影視等領(lǐng)域的廣泛應(yīng)用和發(fā)展前景。 ??????在Unity中想

    2024年02月11日
    瀏覽(18)
  • Vue實(shí)現(xiàn)自定義音頻播放器組件

    Vue實(shí)現(xiàn)自定義音頻播放器組件

    template javascript less 文檔參考 關(guān)于 Audio 自定義樣式 H5 audio 音頻標(biāo)簽自定義樣式修改以及添加播放控制事件

    2024年02月12日
    瀏覽(18)
  • 【uniapp】小程序開發(fā):2 安裝uni-ui組件庫(kù)、使用pinia狀態(tài)管理、自定義http請(qǐng)求

    【uniapp】小程序開發(fā):2 安裝uni-ui組件庫(kù)、使用pinia狀態(tài)管理、自定義http請(qǐng)求

    1、安裝 2、配置組件自動(dòng)導(dǎo)入 使用 npm 安裝好 uni-ui 之后,需要配置 easycom 規(guī)則,讓 npm 安裝的組件支持 easycom 打開項(xiàng)目根目錄下的 pages.json 并添加 easycom 節(jié)點(diǎn): 3、安裝插件,實(shí)現(xiàn)uni-ui組件的類型提示 安裝完成后,在 tsconfig.json 中增加配置項(xiàng) 4、測(cè)試使用 隨便復(fù)制一個(gè)組件在

    2024年02月08日
    瀏覽(21)
  • Unity 之利用Audio Source(音頻源)組件用于播放聲音

    Unity 之利用Audio Source(音頻源)組件用于播放聲音

    Unity中的Audio Source(音頻源)是一個(gè)用于播放聲音的組件,通常附加到游戲?qū)ο笊希员阍谟螒蛑胁シ乓纛l效果、音樂或?qū)υ挕R韵率茿udio Source的詳細(xì)介紹: 添加Audio Source : 要在Unity中使用Audio Source,首先需要將其附加到一個(gè)游戲?qū)ο笊?。通常,您可以選擇場(chǎng)景中的一個(gè)空游

    2024年02月09日
    瀏覽(24)
  • Unity 音頻插件 - MasterAudio 實(shí)現(xiàn)音頻管理系統(tǒng)

    Unity 音頻插件 - MasterAudio 實(shí)現(xiàn)音頻管理系統(tǒng)

    插件介紹: Master Audio的是一個(gè)整體解決方案,所有的豐富的游戲音頻需求。內(nèi)置的音樂閃避,手動(dòng)和自動(dòng)的聲音觸發(fā)真正的隨機(jī)聲音變化,音頻匯集全3D聲音功能。支持所有出口的手機(jī)游戲平臺(tái),具有一流的性能。 主音頻在線幫助網(wǎng)站可在此處找到: Table of Contents 完整的 主

    2023年04月10日
    瀏覽(26)
  • Unity音頻管理器

    在Unity中,為了管理并播放多個(gè)音效,可以創(chuàng)建一個(gè)音頻管理器類來負(fù)責(zé)加載、緩存和播放音頻剪輯。以下是一個(gè)簡(jiǎn)單的示例,展示如何構(gòu)建一個(gè)基本的音效管理播放器腳本: 要使用這個(gè)音頻管理器,你可以在場(chǎng)景中掛載該腳本的實(shí)例,并在Inspector面板中關(guān)聯(lián)所需的AudioClip

    2024年01月20日
    瀏覽(15)
  • 【unity每日一記】 三大金星之(音頻Audio + 碰撞和觸發(fā)+光源組件)

    【unity每日一記】 三大金星之(音頻Audio + 碰撞和觸發(fā)+光源組件)

    ?????個(gè)人主頁(yè) :@元宇宙-秩沅 ????? hallo 歡迎 點(diǎn)贊?? 收藏? 留言?? 加關(guān)注?! ????? 本文由 秩沅 原創(chuàng) ????? 收錄于專欄 : unity每日一記 ?【Unityc#專題篇】之c#系統(tǒng)化大禮包】 ?【unity數(shù)據(jù)持久化】數(shù)據(jù)管理類_PlayerPrfs ?【unity本站最全系列】unity常用API大全

    2024年02月14日
    瀏覽(44)
  • Unity零基礎(chǔ)到進(jìn)階 ??| 音頻源Audio Source組件 詳解

    Unity零基礎(chǔ)到進(jìn)階 ??| 音頻源Audio Source組件 詳解

    ?? 博客主頁(yè):https://xiaoy.blog.csdn.net ?? 本文由 呆呆敲代碼的小Y 原創(chuàng),首發(fā)于 CSDN ?? ?? 學(xué)習(xí)專欄推薦:

    2024年02月13日
    瀏覽(21)
  • Unity零基礎(chǔ)到入門 ??| 音頻源Audio Source組件 詳解

    Unity零基礎(chǔ)到入門 ??| 音頻源Audio Source組件 詳解

    ?? 博客主頁(yè):https://xiaoy.blog.csdn.net ?? 本文由 呆呆敲代碼的小Y 原創(chuàng),首發(fā)于 CSDN ?? ?? 學(xué)習(xí)專欄推薦:

    2024年02月12日
    瀏覽(18)
  • 微信小程序開發(fā)(第五期):npm包的使用、Vant Weapp 組件庫(kù)的使用 && API Promise優(yōu)化 、全局狀態(tài)管理 && store 、分包、分包預(yù)下載 && 自定義配置tabBar

    微信小程序開發(fā)(第五期):npm包的使用、Vant Weapp 組件庫(kù)的使用 && API Promise優(yōu)化 、全局狀態(tài)管理 && store 、分包、分包預(yù)下載 && 自定義配置tabBar

    LiuJInTao:2024年4月6日 一、小程序?qū)?npm 包的限制 二、Vant Weapp 組件庫(kù) 1. 什么是 Vant Weapp 官網(wǎng)文檔地址 2. Vant Weapp 組件庫(kù)的安裝 注意點(diǎn): 我們最新版本的微信開發(fā)者工具是不是沒有勾選npm的,默認(rèn)系統(tǒng)內(nèi)部自動(dòng)勾選。 步驟一 通過 npm 安裝 使用npm構(gòu)建前,請(qǐng)先閱讀微信官方的

    2024年04月27日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包