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

 

效果

自动维护一个 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音效管理类的资料请关注编程宝库其它相关文章!

当前的Winform分页控件中,当前导出的数据一般使用Excel来处理,Excel的文档可以用于后期的数据展示或者批量导入做准备,因此是比较好的输入输出格式。但是有框架的使用客户希望分页控件 ...