美文网首页
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