Files

322 lines
10 KiB
C#
Raw Permalink Normal View History

2026-04-20 12:06:34 +08:00
using FairyGUI;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Events;
namespace BallKingdomCrush
{
public sealed class AudioManager : BaseUnityManager<AudioManager>
{
public const bool IsUnscaleTime = true;
private Dictionary<string, AudioClip> audioClipCacheDict = new Dictionary<string, AudioClip>();
private GameObject newEffectSourcesRoot;
private GameObject dynamicEffectSourcesRoot;
[HideInInspector] public AudioListener audioListener;
[HideInInspector] public AudioSource bgmSource;
[HideInInspector] public AudioSource effectSource;
[HideInInspector] public List<AudioSource> dynamicEffectSources = new List<AudioSource>();
[HideInInspector] public List<AudioSource> unscaleTimeSounds = new List<AudioSource>();
[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<AudioListener>();
bgmSource = gameObject.AddComponent<AudioSource>();
bgmSource.playOnAwake = false;
bgmSource.loop = true;
effectSource = gameObject.AddComponent<AudioSource>();
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<AudioClip>("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<AudioSource>();
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;
}
}
}