Unity實(shí)現(xiàn)高效的音效管理類(lèi)的示例代碼
效果

自動(dòng)維護(hù)一個(gè) AudioSource的池子
如果超過(guò)了池子的峰值 池子會(huì)生成一個(gè)新的AudioSource對(duì)象來(lái)進(jìn)行擴(kuò)容
- 支持2D音效調(diào)用方式 public void PlaySound( string url, float volume = 1.0f, bool loop = false )
- 支持2D音樂(lè)調(diào)用方式 public void PlayMusic( string url, float volume = 1.0f, bool loop = true )
- 支持3D音效調(diào)用方式 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>
/// 初始化 給音效節(jié)點(diǎn)們一個(gè)爸爸
/// </summary>
/// <param name="root"></param>
public void Init( Transform root )
{
transform = root;
LoadAudioClip();//默認(rèn)音效加載
}
/// <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>
/// 緩存一個(gè)音效到池子里
/// </summary>
/// <param name="audioClip"></param>
public void Cache( AudioClip audioClip )
{
if ( !audioClips.ContainsKey( audioClip.name ) )
{
audioClips.Add( audioClip.name, audioClip );
}
}
/// <summary>
/// 需要主動(dòng)去調(diào)用這個(gè)更新檢查 當(dāng)然你也可以開(kāi)一個(gè)定時(shí)器來(lái)檢測(cè)
/// </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>
/// 設(shè)置 音效系統(tǒng)音量 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>
/// 設(shè)置 音樂(lè)系統(tǒng)音量 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>
/// 設(shè)置音效靜音狀態(tài)
/// </summary>
/// <param name="isMute"></param>
public void SetSoundMuteState( bool isMute )
{
soundMute = isMute;
foreach ( var asource in soundSources )
{
asource.mute = soundMute;
}
}
/// <summary>
/// 設(shè)置音樂(lè)靜音狀態(tài)
/// </summary>
/// <param name="isMute"></param>
public void SetMusicMuteState( bool isMute )
{
musicMute = isMute;
foreach ( var asource in musicSources )
{
asource.mute = musicMute;
}
}
/// <summary>
/// 播放音樂(lè) 默認(rèn)循環(huán)播放
/// </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相關(guān)的音效
/// 因?yàn)槭强梢酝瑫r(shí)存在多個(gè)相同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>
/// 播放音效 默認(rèn)單次播放
/// </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世界播放一個(gè)音效 指定一個(gè)位置
/// </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實(shí)現(xiàn)高效的音效管理類(lèi)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Unity音效管理類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Unity的IPostprocessBuild實(shí)用案例深入解析
- Unity的IPreprocessBuild實(shí)用案例深入解析
- Unity的IFilterBuildAssemblies實(shí)用案例深入解析
- Unity InputFiled TMP屬性和各種監(jiān)聽(tīng)示例詳解
- Unity TextMeshPro實(shí)現(xiàn)富文本超鏈接默認(rèn)字體追加字體
- Unity技術(shù)手冊(cè)之Button按鈕使用實(shí)例詳解
- Unity技術(shù)手冊(cè)之Slider滑動(dòng)器使用實(shí)例詳解
- Unity中的RegisterPlugins實(shí)用案例深入解析
相關(guān)文章
C#中通過(guò)LRU實(shí)現(xiàn)通用高效的超時(shí)連接探測(cè)
這篇文章主要介紹了c#中通過(guò)LRU實(shí)現(xiàn)通用高效的超時(shí)連接探測(cè),非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2018-11-11
在Unity中實(shí)現(xiàn)簡(jiǎn)單的偽時(shí)間同步
這篇文章主要介紹了在Unity中實(shí)現(xiàn)簡(jiǎn)單的偽時(shí)間同步,為什么說(shuō)是偽同步呢,因?yàn)閮H僅是獲取的數(shù)據(jù)庫(kù)所在服務(wù)器的系統(tǒng)時(shí)間,分享給大家,有需要的小伙伴可以參考下2015-03-03
C#12中的Collection expressions集合表達(dá)式語(yǔ)法糖詳解
C#12中引入了新的語(yǔ)法糖來(lái)創(chuàng)建常見(jiàn)的集合,并且可以使用..來(lái)解構(gòu)集合,將其內(nèi)聯(lián)到另一個(gè)集合中,下面就跟隨小編一起學(xué)習(xí)一下C#12中這些語(yǔ)法糖的使用吧2023-11-11
C#里SuperSocket庫(kù)不能發(fā)現(xiàn)命令的原因
這篇文章主要介紹C#里SuperSocket庫(kù)不能發(fā)現(xiàn)命令的原因,在使用SuperSocket來(lái)寫(xiě)服務(wù)器的過(guò)程中,這是一個(gè)非??焖俚拈_(kāi)發(fā)方式,也非常好用。不過(guò)學(xué)習(xí)的曲線有點(diǎn)高,在使用的過(guò)程中經(jīng)常會(huì)遇到各種各樣的問(wèn)題。下面來(lái)看看學(xué)習(xí)舉例說(shuō)明吧2021-10-10

