【Unity】音频管理器---拿来即用

发布时间:2024年01月10日

? 使用前提:所有场景共用一个主相机,因为所有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;
            }
        }
    }
    
}
文章来源:https://blog.csdn.net/Xz616/article/details/135445516
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。