Unity实现高效的音效管理类的示例代码

2023-03-22 17:03:42 示例 高效 音效

效果

自动维护一个 AudiOSource的池子

如果超过了池子的峰值 池子会生成一个新的AudioSource对象来进行扩容

  • 支持2D音效调用方式 public void PlaySound( string url, float volume = 1.0f, bool loop = false )
  • 支持2D音乐调用方式 public void PlayMusic( string url, float volume = 1.0f, bool loop = true )
  • 支持3D音效调用方式 public void PlaySoundAtPoint( string url, Vector3 position, float volume = 1f )

食用方式

更改这块的加载 用你们自己框架里的加载方式 或者 走 Resource.Load

源码

using ResourceFramework;
using System.Collections.Generic;
using UnityEngine;

public class AudioManager : SingleTon<AudioManager>
{

    Queue<AudioSource> freeAudioSources = new Queue<AudioSource>();
    List<AudioSource> activeAudioSources = new List<AudioSource>();
    Dictionary<string, List<AudioSource>> playingSources = new Dictionary<string, List<AudioSource>>();
    List<AudioSource> musicSources = new List<AudioSource>();
    List<AudioSource> soundSources = new List<AudioSource>();
    Dictionary<string, Audioclip> audioClips = new Dictionary<string, AudioClip>();

    TransfORM transform;
    public float soundVolume { private set; get; } = 1.0f;
    public float musicVolume { private set; get; } = 1.0f;
    public bool soundMute { private set; get; } = false;
    public bool musicMute { private set; get; } = false;

    /// <summary>
    /// 初始化 给音效节点们一个爸爸
    /// </summary>
    /// <param name="root"></param>
    public void Init( Transform root )
    {
        transform = root;
        LoadAudioClip();//默认音效加载
    }

    /// <summary>
    /// 加载本地音效到音效缓存池
    /// </summary>
    /// <param name="url"></param>
    public void LoadAudioClip( string url = "Assets/AssetBundle/Sounds" )
    {

        AudioClip[] clips = null;
        //#if UNITY_EDITOR
        //        var files = System.IO.Directory.GetFiles( url );
        //        var clipList = new List<AudioClip>();
        //        foreach ( var file in files )
        //        {
        //            var ac = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>( file );
        //            if ( null != ac )
        //            {
        //                clipList.Add( ac );
        //            }
        //        }
        //        clips = clipList.ToArray();

        //#else
        List<AudioClip> clipList = new List<AudioClip>();
        for ( int i = 0; i < AllSoundName.allSoundPath.Length; i++ )
        {
            clipList.Add( Loader.LoadAsset<AudioClip>( $"{url}/{AllSoundName.allSoundPath[ i ]}.mp3" ) );
        }
        clips = clipList.ToArray();

        //#endif




        foreach ( var clip in clips )
        {
            audioClips.Add( clip.name, clip );
        }
    }

    /// <summary>
    /// 缓存一个音效到池子里
    /// </summary>
    /// <param name="audioClip"></param>
    public void Cache( AudioClip audioClip )
    {
        if ( !audioClips.ContainsKey( audioClip.name ) )
        {
            audioClips.Add( audioClip.name, audioClip );
        }
    }

    /// <summary>
    /// 需要主动去调用这个更新检查  当然你也可以开一个定时器来检测
    /// </summary>
    public void OnUpdate()
    {
        for ( int i = 0; i < activeAudioSources.Count; i++ )
        {
            if ( !activeAudioSources[ i ].isPlaying )
            {
                var free = activeAudioSources[ i ];
                free.gameObject.SetActive( false );
                freeAudioSources.Enqueue( free );
                activeAudioSources.RemoveAt( i-- );

                soundSources.Remove( free );
                musicSources.Remove( free );
            }
        }
    }

    /// <summary>
    /// 设置 音效系统音量 0~1
    /// </summary>
    /// <param name="volume"></param>
    public void SetSoundSysVolume( float volume )
    {
        float newVolume = Mathf.Clamp( volume, 0, 1 );
        float scale = newVolume / soundVolume;
        soundVolume = newVolume;

        foreach ( var asource in soundSources )
        {
            asource.volume *= scale;
        }
    }
    /// <summary>
    /// 设置 音乐系统音量 0~1
    /// </summary>
    /// <param name="volume"></param>
    public void SetMusicSysVolume( float volume )
    {
        float newVolume = Mathf.Clamp( volume, 0, 1 );
        float scale = newVolume / musicVolume;
        musicVolume = newVolume;

        foreach ( var asource in musicSources )
        {
            asource.volume *= scale;
        }
    }

    /// <summary>
    /// 设置音效静音状态
    /// </summary>
    /// <param name="isMute"></param>
    public void SetSoundMuteState( bool isMute )
    {
        soundMute = isMute;
        foreach ( var asource in soundSources )
        {
            asource.mute = soundMute;
        }
    }

    /// <summary>
    /// 设置音乐静音状态
    /// </summary>
    /// <param name="isMute"></param>
    public void SetMusicMuteState( bool isMute )
    {
        musicMute = isMute;
        foreach ( var asource in musicSources )
        {
            asource.mute = musicMute;
        }
    }

    /// <summary>
    /// 播放音乐 默认循环播放
    /// </summary>
    /// <param name="url"></param>
    /// <param name="volume"></param>
    /// <param name="loop"></param>
    public void PlayMusic( string url, float volume = 1.0f, bool loop = true )
    {

        if ( freeAudioSources.Count == 0 )
        {
            GenAudioSouceNew();
        }
        var audioSource = freeAudioSources.Dequeue();
        activeAudioSources.Add( audioSource );
        Recoverd( url, audioSource );
        audioSource.gameObject.SetActive( true );
        audioSource.volume = volume * musicVolume;
        audioSource.mute = soundMute;
        audioSource.loop = loop;
        audioSource.spatialBlend = 0f;
        audioSource.clip = GetAudioClip( url );
        audioSource.Play();

        if ( soundSources.Contains( audioSource ) )
        {
            soundSources.Remove( audioSource );
        }
        if ( !musicSources.Contains( audioSource ) )
        {
            musicSources.Add( audioSource );
        }
    }

    /// <summary>
    /// 停掉所有url相关的音效
    /// 因为是可以同时存在多个相同url的音效的  它们都有自己的生命周期
    /// </summary>
    /// <param name="url"></param>
    public void StopMusic( string url )
    {
        if ( playingSources.ContainsKey( url ) )
        {
            playingSources[ url ].ForEach( s => s.Stop() );
            playingSources.Remove( url );
        }
    }

    /// <summary>
    /// 播放音效 默认单次播放
    /// </summary>
    /// <param name="url"></param>
    /// <param name="volume"></param>
    /// <param name="loop"></param>
    public void PlaySound( string url, float volume = 1.0f, bool loop = false )
    {
        if ( freeAudioSources.Count == 0 )
        {
            GenAudioSouceNew();
        }
        var audioSource = freeAudioSources.Dequeue();
        activeAudioSources.Add( audioSource );
        Recoverd( url, audioSource );
        audioSource.gameObject.SetActive( true );
        audioSource.volume = volume * soundVolume;
        audioSource.mute = soundMute;
        audioSource.loop = loop;
        audioSource.spatialBlend = 0f;
        audioSource.clip = GetAudioClip( url );
        audioSource.Play();


        if ( musicSources.Contains( audioSource ) )
        {
            musicSources.Remove( audioSource );
        }
        if ( !soundSources.Contains( audioSource ) )
        {
            soundSources.Add( audioSource );
        }
    }


    /// <summary>
    /// 3D世界播放一个音效  指定一个位置
    /// </summary>
    /// <param name="url"></param>
    /// <param name="position"></param>
    /// <param name="volume"></param>
    public void PlaySoundAtPoint( string url, Vector3 position, float volume = 1f )
    {
        if ( freeAudioSources.Count == 0 )
        {
            GenAudioSouceNew();
        }
        var audioSource = freeAudioSources.Dequeue();
        activeAudioSources.Add( audioSource );
        Recoverd( url, audioSource );
        audioSource.gameObject.transform.position = position;
        audioSource.gameObject.SetActive( true );
        audioSource.clip = GetAudioClip( url );
        audioSource.volume = volume * soundVolume;
        audioSource.mute = soundMute;
        audioSource.loop = false;
        audioSource.spatialBlend = 1f;
        audioSource.Play();
    }

    public void PlayClipAtPoint( AudioClip clip, Vector3 position, float volume = 1f )
    {
        foreach ( var item in audioClips )
        {
            if ( item.Value == clip )
            {
                PlaySoundAtPoint( item.Key, position, volume );
                break;
            }
        }
    }

    public AudioClip GetAudioClip( string url )
    {
        AudioClip clip = null;
        if ( audioClips.TryGetValue( url, out clip ) )
        {
            return clip;
        }
        return null;
    }

    private void GenAudioSouceNew()
    {
        var obj = new GameObject( $"AudioComponent_{( activeAudioSources.Count + freeAudioSources.Count )}" );
        obj.transform.SetParent( transform, true );
        var asource = obj.AddComponent<AudioSource>();
        asource.loop = false;
        asource.volume = 0;
        asource.playOnAwake = false;
        asource.mute = false;
        freeAudioSources.Enqueue( asource );
    }

    private void Recoverd( string url, AudioSource ac )
    {
        List<AudioSource> result = null;
        if ( !playingSources.TryGetValue( url, out result ) )
        {
            result = new List<AudioSource>();
            playingSources.Add( url, result );
        }
        result.Add( ac );
    }
}

以上就是Unity实现高效的音效管理类的示例代码的详细内容,更多关于Unity音效管理类的资料请关注其它相关文章!

相关文章