Unity實現高效的音效管理類的示例代碼
更新時間:2023年03月22日 10:28:47 作者:極客柒
這篇文章主要為大家詳細介紹了如何通過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>
/// 初始化 給音效節(jié)點們一個爸爸
/// </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>
/// 設置 音效系統(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>
/// 設置 音樂系統(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>
/// 設置音效靜音狀態(tài)
/// </summary>
/// <param name="isMute"></param>
public void SetSoundMuteState( bool isMute )
{
soundMute = isMute;
foreach ( var asource in soundSources )
{
asource.mute = soundMute;
}
}
/// <summary>
/// 設置音樂靜音狀態(tài)
/// </summary>
/// <param name="isMute"></param>
public void SetMusicMuteState( bool isMute )
{
musicMute = isMute;
foreach ( var asource in musicSources )
{
asource.mute = musicMute;
}
}
/// <summary>
/// 播放音樂 默認循環(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相關的音效
/// 因為是可以同時存在多個相同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音效管理類的資料請關注腳本之家其它相關文章!
相關文章
C#編程調用Cards.dll實現圖形化發(fā)牌功能示例
這篇文章主要介紹了C#編程調用Cards.dll實現圖形化發(fā)牌功能,結合實例形式分析了C#動態(tài)鏈接庫調用及圖形操作技巧,需要的朋友可以參考下2017-06-06
DevExpress實現GridControl刪除所有行的方法
這篇文章主要介紹了DevExpress實現GridControl刪除所有行的方法,對于C#初學者有一定的參考借鑒價值,需要的朋友可以參考下2014-08-08
.net使用Aspose.Words進行Word替換操作的實現代碼
之前在工作中,需要實現Word打印功能,并且插入圖片。當時采取的方式則是使用書簽進行操作。首先在word內插入書簽,完成后,存為模板。程序加載該模板,找到書簽,并在指定位置寫入文字即可2013-05-05

