美文网首页
Unity中,基本的音乐音效控制系统(改良)

Unity中,基本的音乐音效控制系统(改良)

作者: 全新的饭 | 来源:发表于2022-06-28 11:47 被阅读0次

    相关文档

    原音效控制系统:Unity中,基本的音乐音效控制系统
    按钮的点击效果(缩放、声音):Unity中,按钮按下抬起的缩放效果

    改良内容

    不再需要自行创建相关GO。当调用Instance时,若不存在,会自动创建相关的GO。

    public AudioClip _clip;
    public AudioClip _music;
    
    Audio.AudioSys.Instance.PlaySound(_clip);
    Audio.AudioSys.Instance.PlayMusic(_music);
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace Audio
    {
        public class AudioSys : MonoBehaviour
        {
            private AudioSource _asMusic;
            private AudioSource _asSound;
    
            public const float SoundDefaultVolume = 1f;
            public const float MusicDefaultVolume = 0.5f;
    
            private static AudioSys _instance;
            public static AudioSys Instance
            {
                get
                {
                    if (_instance == null)
                    {
                        GameObject go = new GameObject(nameof(AudioSys));
                        _instance = go.AddComponent<AudioSys>();
                        var parentGo = GameObject.Find("Singleton");
                        if (parentGo == null)
                        {
                            parentGo = new GameObject("Singleton");
                            UnityEngine.Object.DontDestroyOnLoad(parentGo);
                        }
    
                        go.transform.SetParent(parentGo.transform);
    
                        _instance.Init();
                    }
                    return _instance;
                }
            }
    
            #region 音量存储
            public float MusicVolume
            {
                get
                {
                    return PlayerPrefs.GetFloat(MusicVolumeStorageKey, MusicDefaultVolume);
                }
                set
                {
                    value = Mathf.Clamp01(value);
                    _asMusic.volume = value;
                    PlayerPrefs.SetFloat(MusicVolumeStorageKey, value);
                }
            }
            private const string MusicVolumeStorageKey = "AudioSysMusicVolume";
    
            public float SoundVolume
            {
                get
                {
                    return PlayerPrefs.GetFloat(SoundVolumeStorageKey, SoundDefaultVolume);
                }
                set
                {
                    value = Mathf.Clamp01(value);
                    _asSound.volume = value;
                    PlayerPrefs.SetFloat(SoundVolumeStorageKey, value);
                }
            }
            private const string SoundVolumeStorageKey = "AudioSysSoundVolume";
            #endregion
    
            private Dictionary<string, AudioClip> _soundClipDict;
            private Dictionary<string, AudioClip> _musicClipDict;
    
            private void Init()
            {
                // 创建 _asMusic 和 _asSound
                _asMusic = CreateAudioSourceGo("Music");
                _asSound = CreateAudioSourceGo("Sound");
    
                _asMusic.volume = MusicVolume;
                _asSound.volume = SoundVolume;
    #if UNITY_EDITOR
                Debug.Log(string.Format("当前音乐和音效的音量分别是:{0},{1}", _asMusic.volume, _asSound.volume));
    #endif
                _soundClipDict = new Dictionary<string, AudioClip>();
                _musicClipDict = new Dictionary<string, AudioClip>();
            }
    
            private AudioSource CreateAudioSourceGo(string goName)
            {
                GameObject go = new GameObject(goName);
                var audioSource = go.AddComponent<AudioSource>();
                audioSource.playOnAwake = false;
                go.transform.SetParent(transform);
                return audioSource;
            }
    
            public void Destroy()
            {
                _soundClipDict.Clear();
                _soundClipDict = null;
    
                _musicClipDict.Clear();
                _musicClipDict = null;
    
                Destroy(Instance.gameObject);
                _instance = null;
            }
    
            #region 播放音效:可以使用外部AudioSource,也可直接传入音效。可直接传音效资源,也可直接传路径(必须在Resources目录下)
            public void PlaySound(AudioClip clip)
            {
                PlaySound(clip, _asSound);
            }
            public void PlaySound(AudioClip clip, AudioSource audioSource)
            {
                audioSource.volume = SoundVolume;
                audioSource.PlayOneShot(clip);
            }
            public void PlaySound(string clipPath)
            {
                PlaySound(clipPath, _asSound);
            }
            public void PlaySound(string clipPath, AudioSource audioSource)
            {
                audioSource.volume = SoundVolume;
                Play(clipPath, _soundClipDict, audioSource, PlaySound);
            }
            #endregion
    
            public void PlayMusic(string clipPath)
            {
                Play(clipPath, _musicClipDict, _asMusic, PlayMusic);
            }
            public void PlayMusic(AudioClip clip)
            {
                StopPlayMusicCoroutine();
    
                if (_asMusic.clip == null)
                {
                    _asMusic.clip = clip;
                    _asMusic.loop = true;
                    _asMusic.Play();
                }
                else
                {
                    StartPlayMusicCoroutine(clip);
                }
            }
            private void PlayMusic(AudioClip clip, AudioSource audioSource)
            {
                PlayMusic(clip);
            }
    
            private IEnumerator _playMusicCoroutine;
            private IEnumerator PlayMusicCoroutine(AudioClip newClip)
            {
                float maxVolume = _asMusic.volume;
                float minVolume = 0f;
                float duration = 1f;
                float timer = 0f;
                while (timer < duration)
                {
                    _asMusic.volume = Mathf.Lerp(maxVolume, minVolume, timer / duration);
                    timer += Time.unscaledDeltaTime;
                    yield return null;
                }
    
                _asMusic.volume = minVolume;
                _asMusic.clip = newClip;
                _asMusic.Play();
    
                maxVolume = MusicVolume;
                timer = 0f;
                while (timer < duration)
                {
                    _asMusic.volume = Mathf.Lerp(minVolume, maxVolume, timer / duration);
                    timer += Time.unscaledDeltaTime;
                    yield return null;
                }
                _asMusic.volume = maxVolume;
    
            }
            private void StartPlayMusicCoroutine(AudioClip newClip)
            {
                _playMusicCoroutine = PlayMusicCoroutine(newClip);
                StartCoroutine(_playMusicCoroutine);
            }
            private void StopPlayMusicCoroutine()
            {
                if (_playMusicCoroutine != null)
                {
                    StopCoroutine(_playMusicCoroutine);
                    _playMusicCoroutine = null;
                }
            }
    
            private void Play(string clipPath, Dictionary<string, AudioClip> dict, AudioSource audioSource, Action<AudioClip, AudioSource> action)
            {
                if (!dict.ContainsKey(clipPath))
                {
                    var clip = Resources.Load<AudioClip>(clipPath);
                    if (clip != null)
                    {
                        dict.Add(clipPath, clip);
    #if UNITY_EDITOR
                        Debug.Log("添加声音资源到音频管理系统:" + clipPath);
    #endif
                    }
                }
    
                if (dict.ContainsKey(clipPath))
                {
                    action?.Invoke(dict[clipPath], audioSource);
                }
            }
        }
    }
    

    音效控制界面:AudioWnd
    2个按钮,分别拥有2个状态:静音、非静音。通过点击在2个状态间切换。


    image.png
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    
    // 2个开关,分别控制音乐、音效的音量。
    public class AudioWnd : MonoBehaviour
    {
        private GameSys _gameSys;
        [SerializeField]
        private GameObject _wndGo;
        [SerializeField, Header("按钮:音乐")]
        private AudioWndBtn _musicBtn;
        [SerializeField, Header("按钮:音效")]
        private AudioWndBtn _soundBtn;
    
        private void OnEnable() 
        {
            Open();
        }
    
        private void Start()
        {
            Init();
        }
    
        private void OnDisable() 
        {
            Close();
        }
    
        private void OnDestroy()
        {
            Destroy();
        }
    
        public void Init()
        {
            _musicBtn.Button.onClick.AddListener(OnClickMusicBtn);
            _soundBtn.Button.onClick.AddListener(OnClickSoundBtn);
            Open();
        }
    
        public void Destroy()
        {
            _musicBtn.Button.onClick.RemoveListener(OnClickMusicBtn);
            _soundBtn.Button.onClick.RemoveListener(OnClickSoundBtn);
        }
    
        private void Open()
        {
            RefreshBtnState();
            _wndGo.SetActive(true);
    
            void RefreshBtnState()
            {
                _musicBtn.RefreshState(IsMute(Audio.AudioSys.Instance.MusicVolume));
                _soundBtn.RefreshState(IsMute(Audio.AudioSys.Instance.SoundVolume));
            }
        }
    
        private void Close()
        {
            _wndGo.SetActive(false);
        }
    
        private void OnClickMusicBtn()
        {
            bool isMute = IsMute(Audio.AudioSys.Instance.MusicVolume);
            Audio.AudioSys.Instance.MusicVolume = isMute ? Audio.AudioSys.MusicDefaultVolume : 0;
    
            _musicBtn.RefreshState(IsMute(Audio.AudioSys.Instance.MusicVolume));
        }
        private void OnClickSoundBtn()
        {
            bool isMute = IsMute(Audio.AudioSys.Instance.SoundVolume);
            Audio.AudioSys.Instance.SoundVolume = isMute ? Audio.AudioSys.SoundDefaultVolume : 0;
    
            _soundBtn.RefreshState(IsMute(Audio.AudioSys.Instance.SoundVolume));
        }
    
        private bool IsMute(float volume)
        {
            return volume == 0;
        }
    
        [System.Serializable]
        private class AudioWndBtn
        {
            public Button Button;
            [Header("外观:非静音")]
            public GameObject NonMuteGo;
            [Header("外观:静音")]
            public GameObject MuteGo;
    
            public void RefreshState(bool isMute)
            {
                NonMuteGo.SetActive(!isMute);
                MuteGo.SetActive(isMute);
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Unity中,基本的音乐音效控制系统(改良)

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