? 使用前提:所有场景共用一个主相机,因为所有audiosorce会放在主相机下面
? 包含:普通音频、3D音频、背景音频
? 资源:放在Sounds文件夹下
? 资源路径:采用id+路径配表方式读取资源路径加载
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioMgr : Singleton<AudioMgr>
{
private string soundRootPath = "Sounds/{0}";
private GameObject AudioSourcesRoot;
public float AudioBackgroundVolumns = 1F; //背景音量
public float AudioBackgroundPitch = 1f; //背景音乐的音调
public float AudioSoundEffectsVolumns = 1.0f; // 音效音量
private AudioSource audioSourceBackgroundAudio; //背景音乐
private List<AudioSource> multipleAudios = new List<AudioSource>();//音效列表
private Dictionary<int, AudioClip> multipleAudioClips = new Dictionary<int, AudioClip>();
private Dictionary<GameObject, Dictionary<int, AudioSource>> Audio3d =
new Dictionary<GameObject, Dictionary<int, AudioSource>>();
private bool isMute = false;
public bool IsMute
{
get { return isMute; }
}
public void Init()
{
AudioSourcesRoot = new GameObject("AudioSourcesRoot");
AudioSourcesRoot.transform.SetParent(CameraMgr.Instance.MainCamera.transform);
AudioSourcesRoot.transform.localPosition = Vector3.zero;
audioSourceBackgroundAudio = CameraMgr.Instance.MainCamera.gameObject.AddComponent<AudioSource>();
}
public void Release()
{
StopAllMultipleSound();
ClearIdleMultipleAudioSource();
multipleAudioClips.Clear();
ClearIdle3dAudioSource();
Audio3d.Clear();
}
/// <summary>
/// 静音
/// </summary>
/// <param name="isMute"></param>
public void SetMute(bool isMute)
{
if (this.isMute != isMute)
{
this.isMute = isMute;
for (int i = 0; i < multipleAudios.Count; i++)
{
multipleAudios[i].mute = this.isMute;
}
audioSourceBackgroundAudio.mute = this.isMute;
foreach (KeyValuePair<GameObject,Dictionary<int,AudioSource>> valuePair in Audio3d)
{
if (valuePair.Key == null)
{
continue;
}
foreach (KeyValuePair<int,AudioSource> keyValuePair in valuePair.Value)
{
if (keyValuePair.Value != null)
{
keyValuePair.Value.mute = this.isMute;
}
}
}
}
}
/// <summary>
/// 播放背景音乐
/// 传入的参数是背景音乐的id
/// </summary>
/// <param name="soundId">音效id</param>
public void PlayBackground(int soundId)
{
SoundData sound = DataMgr.GetSoundData(soundId);
AudioClip audioClip = ResMgr.Instance.Load<AudioClip>(String.Format(soundRootPath, sound.resourcePath));
//防止背景音乐的重复播放。
if (audioSourceBackgroundAudio.clip == audioClip)
{
return;
}
audioSourceBackgroundAudio.volume = AudioBackgroundVolumns;
audioSourceBackgroundAudio.pitch = AudioBackgroundPitch;
if (audioClip)
{
audioSourceBackgroundAudio.loop = true; //背景音乐是循环播放的
audioSourceBackgroundAudio.clip = audioClip;
audioSourceBackgroundAudio.Play();
}
else
{
Debug.LogWarning($"[AudioManager.cs/PlayBackground()] audioClip==null ,soundId :{soundId} !");
}
}
/// <summary>
/// 播放普通音频
/// </summary>
/// <param name="soundId"></param>
/// <param name="isLoop"></param>
/// <param name="speed"></param>
/// <param name="volume"></param>
public void PlaySound(int soundId, bool isLoop = false, float speed = 1, float volume = 1f)
{
volume = AudioSoundEffectsVolumns;
if (!multipleAudioClips.TryGetValue(soundId, out AudioClip audioClip))
{
SoundData sound = DataMgr.GetSoundData(soundId);
audioClip = ResMgr.Instance.Load<AudioClip>(String.Format(soundRootPath, sound.resourcePath));
multipleAudioClips[soundId] = audioClip;
}
AudioSource audio = ExtractIdleMultipleAudioSource();
audio.clip = audioClip;
audio.loop = isLoop;
audio.pitch = speed;
audio.volume = volume;
audio.Play();
}
//提取闲置中的多通道音源
private AudioSource ExtractIdleMultipleAudioSource()
{
for (int i = 0; i < multipleAudios.Count; i++)
{
if (!multipleAudios[i].isPlaying)
{
return multipleAudios[i];
}
}
AudioSource audio = CreateAudioSource("MultipleAudio", 1, 1, 1, 0);
multipleAudios.Add(audio);
return audio;
}
/// <summary>
/// 停止播放指定的多通道音效
/// </summary>
/// <param name="clip">音乐剪辑</param>
public void StopSound(int soundId)
{
if (!multipleAudioClips.TryGetValue(soundId, out AudioClip audioClip))
{
SoundData sound = DataMgr.GetSoundData(soundId);
audioClip = ResMgr.Instance.Load<AudioClip>(String.Format(soundRootPath, sound.resourcePath));
multipleAudioClips[soundId] = audioClip;
}
for (int i = 0; i < multipleAudios.Count; i++)
{
if (multipleAudios[i].isPlaying)
{
if (multipleAudios[i].clip == audioClip)
{
multipleAudios[i].Stop();
}
}
}
}
/// <summary>
/// 停止播放所有多通道音效
/// </summary>
public void StopAllMultipleSound()
{
for (int i = 0; i < multipleAudios.Count; i++)
{
if (multipleAudios[i].isPlaying)
{
multipleAudios[i].Stop();
}
}
}
/// <summary>
/// 开始播放所有通道音频
/// </summary>
public void StartAllMultipleSound()
{
for (int i = 0; i < multipleAudios.Count; i++)
{
if (multipleAudios[i].isPlaying)
{
multipleAudios[i].Play();
}
}
}
/// <summary>
/// 销毁所有闲置中的多通道音效的音源
/// </summary>
public void ClearIdleMultipleAudioSource()
{
for (int i = 0; i < multipleAudios.Count; i++)
{
if (!multipleAudios[i].isPlaying)
{
AudioSource audio = multipleAudios[i];
multipleAudios.RemoveAt(i);
i -= 1;
GameObject.Destroy(audio.gameObject);
}
}
}
/// <summary>
/// 创建一个音源
/// </summary>
/// <param name="name"></param>
/// <param name="priority"></param>
/// <param name="volume"></param>
/// <param name="speed"></param>
/// <param name="spatialBlend"></param>
/// <returns></returns>
private AudioSource CreateAudioSource(string name, int priority, float volume, float speed, float spatialBlend)
{
GameObject audioObj = new GameObject(name);
audioObj.transform.SetParent(AudioSourcesRoot.transform);
audioObj.transform.localPosition = Vector3.zero;
audioObj.transform.localRotation = Quaternion.identity;
audioObj.transform.localScale = Vector3.one;
AudioSource audio = audioObj.AddComponent<AudioSource>();
audio.playOnAwake = false;
audio.priority = priority;
audio.volume = volume;
audio.pitch = speed;
audio.spatialBlend = spatialBlend;
audio.mute = isMute;
return audio;
}
//创建一个3d音源
private AudioSource Create3dAudioSource(GameObject parent, string name, int priority, float volume, float speed,
float spatialBlend)
{
GameObject audioObj = new GameObject(name);
audioObj.transform.SetParent(parent.transform);
audioObj.transform.localPosition = Vector3.zero;
audioObj.transform.localRotation = Quaternion.identity;
audioObj.transform.localScale = Vector3.one;
audioObj.transform.SetAsLastSibling();
AudioSource audio = audioObj.AddComponent<AudioSource>();
audio.playOnAwake = false;
audio.priority = priority;
audio.volume = volume;
audio.pitch = speed;
audio.spatialBlend = spatialBlend;
audio.mute = isMute;
return audio;
}
public void Play3DSound(GameObject parent, int soundId, bool isLoop = false, float speed = 1, float volume = 1f)
{
volume = AudioSoundEffectsVolumns;
if (!multipleAudioClips.TryGetValue(soundId, out AudioClip audioClip))
{
SoundData sound = DataMgr.GetSoundData(soundId);
audioClip = ResMgr.Instance.Load<AudioClip>(String.Format(soundRootPath, sound.resourcePath));
multipleAudioClips[soundId] = audioClip;
}
AudioSource audio = Create3dAudioSource(parent, "3dAudio", 1, 1, 1, 0);
if (!Audio3d.TryGetValue(parent,out Dictionary<int,AudioSource> objAudios3d))
{
Audio3d[parent] = new Dictionary<int, AudioSource>();
}
Audio3d[parent][soundId] = audio;
audio.clip = audioClip;
audio.loop = isLoop;
audio.pitch = speed;
audio.volume = volume;
audio.Play();
}
/// <summary>
/// 停止播放3D音效
/// </summary>
public void Stop3dSound(GameObject obj, int soundId)
{
if (!Audio3d.TryGetValue(obj,out Dictionary<int,AudioSource> objAudios3d))
{
return;
}
if (Audio3d[obj].TryGetValue(soundId,out AudioSource Audios3d))
{
Audios3d.Stop();
}
}
/// <summary>
/// 播放3D音效
/// </summary>
public void Start3dSound(GameObject obj, int soundId)
{
if (!Audio3d.TryGetValue(obj,out Dictionary<int,AudioSource> objAudios3d))
{
return;
}
if (Audio3d[obj].TryGetValue(soundId,out AudioSource Audios3d))
{
Audios3d.Play();
}
}
/// <summary>
/// 销毁所有3d音效的音源
/// </summary>
public void ClearIdle3dAudioSource()
{
foreach (KeyValuePair<GameObject,Dictionary<int,AudioSource>> valuePair in Audio3d)
{
if (valuePair.Key == null)
{
continue;
}
foreach (KeyValuePair<int,AudioSource> keyValuePair in valuePair.Value)
{
GameObject.Destroy(keyValuePair.Value.gameObject);
}
}
Audio3d.Clear();
}
/// <summary>
/// 设置背景音乐音量
/// </summary>
/// <param name="volume">音量</param>
public void SetBackgroundMusicVolume(float volume)
{
AudioBackgroundVolumns = volume;
audioSourceBackgroundAudio.volume = AudioBackgroundVolumns;
}
/// <summary>
/// 设置音效音量
/// </summary>
/// <param name="volume">音量</param>
public void SetSoundEffectsVolume(float volume)
{
AudioSoundEffectsVolumns = volume;
//调节2D音效的音量
foreach (var audio in multipleAudios)
{
if (audio == null)
{
continue;
}
audio.volume = volume;
}
// 调节3D音效的音量
foreach (var objAudios in Audio3d.Values)
{
foreach (var audio in objAudios.Values)
{
if (audio == null)
{
continue;
}
audio.volume = volume;
}
}
}
}