using FairyGUI; using UnityEngine; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine.Events; namespace BallKingdomCrush { public sealed class AudioManager : BaseUnityManager { public const bool IsUnscaleTime = true; private Dictionary audioClipCacheDict = new Dictionary(); private GameObject newEffectSourcesRoot; private GameObject dynamicEffectSourcesRoot; [HideInInspector] public AudioListener audioListener; [HideInInspector] public AudioSource bgmSource; [HideInInspector] public AudioSource effectSource; [HideInInspector] public List dynamicEffectSources = new List(); [HideInInspector] public List unscaleTimeSounds = new List(); [HideInInspector] public float currUISoundVolume = 1; private bool isOpenBGM; public bool IsOpenBGM { get { return isOpenBGM; } set { isOpenBGM = value; PlayerPrefsKit.WriteBool(PrefsKeyConst.AudioMgr_isOpenBGM, isOpenBGM); if (!bgmSource) return; bgmSource.enabled = isOpenBGM; if (isOpenBGM) { bgmSource.Play(); } else { bgmSource.Pause(); } } } private bool isOpenEffect; public bool IsOpenEffect { get { return isOpenEffect; } set { isOpenEffect = value; PlayerPrefsKit.WriteBool(PrefsKeyConst.AudioMgr_isOpenEffect, isOpenEffect); GRoot.inst.soundVolume = isOpenEffect ? currUISoundVolume : 0f; if (isOpenEffect) { GRoot.inst.EnableSound(); } else { GRoot.inst.DisableSound(); } } } private void InitAudioMode() { isOpenBGM = PlayerPrefsKit.ReadBool(PrefsKeyConst.AudioMgr_isOpenBGM, true); isOpenEffect = PlayerPrefsKit.ReadBool(PrefsKeyConst.AudioMgr_isOpenEffect, true); GRoot.inst.soundVolume = 1; currUISoundVolume = GRoot.inst.soundVolume; GRoot.inst.soundVolume = isOpenEffect ? currUISoundVolume : 0f; } public override void Init() { base.Init(); AppDispatcher.Instance.AddListener(AppMsg.TimeScale_Change, OnTimeScaleChange); audioListener = gameObject.AddComponent(); bgmSource = gameObject.AddComponent(); bgmSource.playOnAwake = false; bgmSource.loop = true; effectSource = gameObject.AddComponent(); effectSource.playOnAwake = false; effectSource.loop = false; newEffectSourcesRoot = new GameObject("NewEffectSources"); newEffectSourcesRoot.transform.SetParent(gameObject.transform, false); dynamicEffectSourcesRoot = new GameObject("DynamicEffectSources"); dynamicEffectSourcesRoot.transform.SetParent(gameObject.transform, false); InitAudioMode(); } public override void Dispose() { base.Dispose(); AppDispatcher.Instance.RemoveListener(AppMsg.TimeScale_Change, OnTimeScaleChange); } public void InitDefaultButtonClickSound(string btnSound) { string defaultSound = AudioConst.UIButtonDefault; if (!string.IsNullOrEmpty(btnSound)) { defaultSound = btnSound; } LoadKit.Instance.LoadAudio("Audio", defaultSound, audioClip => { if (audioClip != null) { UIConfig.buttonSound = new NAudioClip(audioClip); UIConfig.buttonSoundVolumeScale = 1; } }); } private void OnTimeScaleChange(object value) { if (unscaleTimeSounds.Count != 0) { for (int i = 0; i < unscaleTimeSounds.Count; i++) { AudioSource audioSource = unscaleTimeSounds[i]; if (audioSource) { audioSource.pitch = 1; } } } } public void StopBGM() { bgmSource.Stop(); } public void PlayBGM(string audioName, bool isUnscaleTime = IsUnscaleTime) { if (string.IsNullOrEmpty(audioName)) return; string curName = bgmSource.clip == null ? null : bgmSource.clip.name; if (curName != audioName) { AudioClip currClip = null; if (audioClipCacheDict.TryGetValue(audioName, out var value)) { currClip = value; } else { try { currClip = LoadKit.Instance.LoadAsset("Audio", audioName); } catch (System.Exception) { } } if (currClip != null) { bgmSource.clip = currClip; if (!isOpenBGM) { return; } if (isUnscaleTime) { if (!unscaleTimeSounds.Contains(bgmSource)) { unscaleTimeSounds.Add(bgmSource); } } else { if (unscaleTimeSounds.Contains(bgmSource)) { unscaleTimeSounds.Remove(bgmSource); } } bgmSource.pitch = isUnscaleTime ? 1 : Time.timeScale; bgmSource.Play(); } } } public AudioSource PlayDynamicEffect(string audioName, float delay = 0, bool isLoop = false, bool isUnscaleTime = IsUnscaleTime) { if (!isOpenEffect || string.IsNullOrEmpty(audioName)) return null; AudioSource effectSourceCom = null; for (int i = 0; i < dynamicEffectSources.Count; i++) { AudioSource sourceItem = dynamicEffectSources[i]; if (!sourceItem.isPlaying) { effectSourceCom = sourceItem; break; } } if (effectSourceCom == null) { effectSourceCom = dynamicEffectSourcesRoot.AddComponent(); effectSourceCom.playOnAwake = false; dynamicEffectSources.Add(effectSourceCom); } if (effectSourceCom.loop != isLoop) { effectSourceCom.loop = isLoop; } string curName; AudioClip currClip = null; if (effectSourceCom.clip == null) { curName = null; } else { currClip = effectSourceCom.clip; curName = currClip.name; } var playAction = new UnityAction(delegate { if (currClip != null) { effectSourceCom.clip = currClip; if (isUnscaleTime) { if (!unscaleTimeSounds.Contains(effectSourceCom)) { unscaleTimeSounds.Add(effectSourceCom); } } else { if (unscaleTimeSounds.Contains(effectSourceCom)) { unscaleTimeSounds.Remove(effectSourceCom); } } effectSourceCom.pitch = isUnscaleTime ? 1 : Time.timeScale; if (delay == 0) { effectSourceCom.Play(); } else { effectSourceCom.PlayDelayed(delay); } } }); if (curName != audioName) { if (audioClipCacheDict.ContainsKey(audioName)) { currClip = audioClipCacheDict[audioName]; playAction(); } else { var path = new StringBuilder("Audio"); var strs = audioName.Split('.'); var assetName = strs.Last(); if (strs.Length > 1) { var assetUrl = audioName.Replace($".{assetName}", string.Empty); path.Append(".").Append(assetUrl); } LoadKit.Instance.LoadAudio(path.ToString(), assetName, (clip) => { currClip = clip; audioClipCacheDict[audioName] = clip; playAction(); }); } } else { try { if (delay == 0) { effectSourceCom.Play(); } else { effectSourceCom.PlayDelayed(delay); } } catch (System.Exception) { } } return effectSourceCom; } } }