美文网首页
基于ET框架的Unity游戏音效管理组件

基于ET框架的Unity游戏音效管理组件

作者: 渐渐简书 | 来源:发表于2018-07-05 11:13 被阅读0次

    介绍

    本组件是基于强大的ET框架之上的,此处附上et框架链接:https://github.com/egametang/ET

    当然如果不使用et的话,也可自行修改为单例模式进行使用,非常简单易用

    本音效组件主要分三个文件:

    SoundComponent.cs——游戏音效管理组件

    SoundData.cs——每个音效单元类

    EditorCreateAudio.cs——创建音效预设(Editor类)

    特点:支持控制全局音量变化,音乐静音及音效静音

    流程:.mp3等资源--> . prefab预制体并附上SoundData单元类--> SoundComponent中通过ab加载. prefab并实例化--> SoundComponent调用SoundData去控制每一个音效

    组件部分思路源于海马哥,谢谢!

    SoundData(音效资源类)

    请看代码,一目了然,简单明了

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace ETModel
    {
        [RequireComponent(typeof(AudioSource))]
        public class SoundData : MonoBehaviour
        {
            //音频源控件
            public new AudioSource audio;
    
            /// <summary>
            /// 是否强制重新播放
            /// </summary>
            //[HideInInspector]
            public bool isForceReplay = false;
    
            /// <summary>
            /// 是否循环播放
            /// </summary>
            //[HideInInspector]
            public bool isLoop = false;
    
            /// <summary>
            /// 音量
            /// </summary>
            //[HideInInspector]
            public float volume = 1;
    
            /// <summary>
            /// 延迟
            /// </summary>
            //[HideInInspector]
            public ulong delay = 0;
    
            public AudioSource GetAudio()
            {
                return audio;
            }
    
            public bool IsPlaying
            {
                get
                {
                    return audio != null && audio.isPlaying;
                }
            }
            public bool IsPause
            {
                get;
                set;
            }
            public void Dispose()
            {
                Destroy(gameObject);
            }
    
            /// <summary>
            /// 音效类型
            /// </summary>
            public SoundType Sound { get; set; }
    
            public bool Mute
            {
                get { return audio.mute; }
                set { audio.mute = value; }
            }
    
            public float Volume
            {
                get { return audio.volume; }
                set { audio.volume = value; }
            }
        }
    
        /// <summary>
        /// 音效类型
        /// </summary>
        public enum SoundType
        {
            Music,//长音乐
            Sound,//短音乐
        }
    }
    

    EditorCreateAudio(工具类)

    自动将目录下的音效资源文件创建成Prefab预制体,方便加载和管理

    PS:务必给Prefab加上ab标识,打进需要的ab包,也可以自行在类中拓展标上ab标识的代码

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    using System.IO;
    
    namespace ETModel
    {
        public class EditorCreateAudio : MonoBehaviour
        {
            //音效资源路径
            private static string audiosDir = "assets/ETAB/audios";
            //导出预制体路径
            private static string prefabDir = "assets/ETAB/SoundPrefabs";
    
            [MenuItem("Tools/创建音效预设", priority = 1004)]
            static void CreateAudioPrefab()
            {
                string[] _patterns = new string[] { "*.mp3","*.wav", "*.ogg" };//识别不同的后缀名
                List<string> _allFilePaths = new List<string>();
                foreach (var item in _patterns)
                {
                    string[] _temp = Directory.GetFiles(audiosDir, item, SearchOption.AllDirectories);
                    _allFilePaths.AddRange(_temp);
                }
                foreach (var item in _allFilePaths)
                {
                    System.IO.FileInfo _fi = new System.IO.FileInfo(item);
                    var _tempName = _fi.Name.Replace(_fi.Extension, "").ToLower();
                    AudioClip _clip = AssetDatabase.LoadAssetAtPath<AudioClip>(item);
                    if (null != _clip)
                    {
                        GameObject _go = new GameObject();
                        _go.name = _tempName;
                        AudioSource _as = _go.AddComponent<AudioSource>();
                        _as.playOnAwake = false;
                        SoundData _data = _go.AddComponent<SoundData>();
                        _data.audio = _as;
                        _data.audio.clip = _clip;
                        string path = $"{prefabDir}/{_tempName}.prefab";
                        var temp = PrefabUtility.CreatePrefab(path, _go);
    
                        //添加ab标记
                        AssetImporter importer = AssetImporter.GetAtPath(path);
                        if (importer == null || temp == null)
                        {
                            Debug.LogError("error: " + path);
                            return;
                        }
                        importer.assetBundleName = "sound.unity3d";
    
                        GameObject.DestroyImmediate(_go);
                        EditorUtility.SetDirty(temp);
                        Resources.UnloadAsset(_clip);
                    }
                }
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
        }
    }
    
    

    SoundComponent(音效管理组件)

    各部分我都有注释,各位可以自行理解,简易上手

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using UnityEngine;
    
    namespace ETModel
    {
        [ObjectSystem]
        public class SoundComponentAwakeSystem : AwakeSystem<SoundComponent>
        {
            public override void Awake(SoundComponent self)
            {
                self.Awake();
            }
        }
    
        /// <summary>
        /// 游戏音效管理组件
        /// </summary>
        public class SoundComponent : Component
        {
            public static SoundComponent Instance;
    
            /// <summary>
            /// 控制游戏全局音量
            /// </summary>
            public float SoundVolume
            {
                get
                {
                    return _soundVolume;
                }
                set
                {
                    _soundVolume = Mathf.Clamp(value, 0, 1);
                    foreach (SoundData clip in m_clips.Values)
                    {
                        clip.Volume = _soundVolume * clip.volume;
                    }
                }
            }
            private float _soundVolume = 0.8f;
    
            //所有音效
            private Dictionary<string, SoundData> m_clips = new Dictionary<string, SoundData>();
    
            //根据类型分类所有音效
            private Dictionary<SoundType, Dictionary<string, SoundData>> _allClips = new Dictionary<SoundType, Dictionary<string, SoundData>>()
            { { SoundType.Music, new Dictionary<string, SoundData>() }, { SoundType.Sound, new Dictionary<string, SoundData>() } };
    
            //catch ab资源
            private static Dictionary<string, SoundData> abSounds = new Dictionary<string, SoundData>();
    
            //根物体
            private Transform root;
    
            /// <summary>
            /// 音乐静音
            /// </summary>
            public bool MusicMute
            {
                get { return _musicMute; }
                set
                {
                    _musicMute = value;
                    foreach (var soundData in _allClips[SoundType.Music].Values)
                    {
                        soundData.Mute = _musicMute;
                    }
                    PlayerPrefs.SetInt("MusicMute", value ? 1 : 0);
                }
            }
            private bool _musicMute = false;
    
            /// <summary>
            /// 音效静音
            /// </summary>
            public bool SoundMute
            {
                get { return _soundMute; }
                set
                {
                    _soundMute = value;
                    foreach (var soundData in _allClips[SoundType.Sound].Values)
                    {
                        soundData.Mute = _soundMute;
                    }
                    PlayerPrefs.SetInt("SoundMute", value ? 1 : 0);
                }
            }
            private bool _soundMute = false;
    
            public void Awake()
            {
                Instance = this;
    
                _musicMute = PlayerPrefs.GetInt("MusicMute", 0) == 1;
                _soundMute = PlayerPrefs.GetInt("SoundMute", 0) == 1;
    
                root = new GameObject("SoundDatas").transform;
                GameObject.DontDestroyOnLoad(root.gameObject);
            }
    
            private bool IsContainClip(string clipName)
            {
                lock (m_clips)
                {
                    if (m_clips.ContainsKey(clipName))
                        return true;
                    return false;
                }
            }
    
            private SoundData GetAudioSource(string clipName)
            {
                if (IsContainClip(clipName))
                    return m_clips[clipName];
                return null;
            }
    
            private void AddClip(string clipName, SoundData data, SoundType type)
            {
                lock (m_clips)
                {
                    data.IsPause = false;
                    data.transform.transform.SetParent(root);
                    data.Sound = type;
                    if (IsContainClip(clipName))
                    {
                        m_clips[clipName] = data;
                        _allClips[type][clipName] = data;
                    }
                    else
                    {
                        m_clips.Add(clipName, data);
                        _allClips[type].Add(clipName, data);
                    }
                }
            }
    
            /// <summary>
            /// 短暂的声音和特效
            /// 无法暂停
            /// 异步加载音效
            /// </summary>
            public async void PlayClip(string clipName, float volume = 1)
            {
                SoundData sd = await LoadSound(clipName);
                if (sd != null)
                {
                    sd.volume = Mathf.Clamp(volume, 0, 1);
                    sd.Mute = SoundMute;
                    if (!IsContainClip(clipName))
                    {
                        AddClip(clipName, sd, SoundType.Sound);
                    }
                    PlayMusic(clipName, sd);
                }
                else
                {
                    Log.Error($"没有此音效 ={ clipName}");
                }
            }
    
            /// <summary>
            /// 播放长音乐 背景音乐等
            /// 可以暂停 继续播放
            /// 异步加载音效
            /// </summary>
            /// <param name="clipName">声音的预设名字(不包括前缀路径名)</param>
            /// <param name="delay">延迟播放 单位秒</param>
            /// <param name="volume">音量</param>
            /// <param name="isloop">是否循环播放</param>
            /// /// <param name="forceReplay">是否强制重头播放</param>
            public async void PlayMusic(string clipName, ulong delay = 0, float volume = 1, bool isloop = false, bool forceReplay = false)
            {
                SoundData sd = await LoadSound(clipName);
                if (sd != null)
                {
                    sd.isForceReplay = forceReplay;
                    sd.isLoop = isloop;
                    sd.delay = delay;
                    sd.volume = Mathf.Clamp(volume, 0, 1);
                    sd.Mute = MusicMute;
                    if (!IsContainClip(clipName))
                    {
                        AddClip(clipName, sd, SoundType.Music);
                    }
                    PlayMusic(clipName, sd);
                }
                else
                {
                    Log.Error($"没有此音效 ={ clipName}");
                }
            }
    
            //加载声音
            private async Task<SoundData> LoadSound(string soundName)
            {
                ResourcesComponent resourcesComponent = Game.Scene.GetComponent<ResourcesComponent>();
                if (!abSounds.ContainsKey(soundName) || abSounds[soundName] == null)
                {
                    await resourcesComponent.LoadBundleAsync("sound.unity3d");
                    abSounds.Add(soundName, GameObject.Instantiate((GameObject)resourcesComponent.GetAsset("sound.unity3d", soundName)).GetComponent<SoundData>());
                    resourcesComponent.UnloadBundle("sound.unity3d");
                }
                return abSounds[soundName];
            }
    
            //播放SoundData
            private void PlayMusic(string clipName, SoundData asource)
            {
                if (null == asource)
                    return;
                bool forceReplay = asource.isForceReplay;
                asource.audio.volume = asource.volume * SoundVolume;
                asource.audio.loop = asource.isLoop;
                if (!forceReplay)
                {
                    if (!asource.IsPlaying)
                    {
                        if (!asource.IsPause)
                            asource.audio.Play(asource.delay);
                        else
                            Resume(clipName);
                    }
                }
                else
                {
                    asource.audio.PlayDelayed(asource.delay);
                    asource.audio.PlayScheduled(0);
                }
            }
    
            /// <summary>
            /// 停止并销毁声音
            /// </summary>
            /// <param name="clipName"></param>
            public void Stop(string clipName)
            {
                SoundData data = GetAudioSource(clipName);
                if (null != data)
                {
                    if (_allClips[data.Sound].ContainsKey(clipName))
                    {
                        _allClips[data.Sound].Remove(clipName);
                    }
                    m_clips.Remove(clipName);
                    abSounds.Remove(clipName);
                    data.Dispose();
                }
            }
    
            /// <summary>
            /// 暂停声音
            /// </summary>
            /// <param name="clipName"></param>
            public void Pause(string clipName)
            {
                SoundData data = GetAudioSource(clipName);
                if (null != data)
                {
                    data.IsPause = true;
                    data.audio.Pause();
                }
            }
    
            /// <summary>
            /// 继续播放
            /// </summary>
            /// <param name="clipName"></param>
            public void Resume(string clipName)
            {
                SoundData data = GetAudioSource(clipName);
                if (null != data)
                {
                    data.IsPause = false;
                    data.audio.UnPause();
                }
            }
    
            /// <summary>
            /// 销毁所有声音
            /// </summary>
            public void DisposeAll()
            {
                foreach (var allClip in _allClips.Values)
                {
                    allClip.Clear();
                }
                foreach (var item in m_clips)
                {
                    item.Value.Dispose();
                }
                m_clips.Clear();
            }
        }
    }
    
    

    下载:

    GitHub(国外):

    ET模组仓库: https://github.com/egametang/ET-Modules.git

    本人工具仓库:https://github.com/HealthyChina/HealthyResource.git

    Gitee(国内):

    本人工具仓库:https://gitee.com/healthyZ/HealthyResource.git

    转载请声明出处和作者(渐渐),你的点赞,分享,转发将是对我最大的鼓励!

    码字不易,感谢阅读!

    相关文章

      网友评论

          本文标题:基于ET框架的Unity游戏音效管理组件

          本文链接:https://www.haomeiwen.com/subject/panuuftx.html