相关文档
原音效控制系统: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);
}
}
}
网友评论