using System.Collections.Generic; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; public class ThronefallAudioManager : MonoBehaviour { public class OneshotSource { public AudioSource aSource; public bool available = true; public OneshotSource(AudioSource audioSource) { aSource = audioSource; } } public enum AudioOneShot { BuildingBuild, BuildingUpgrade, CoinslotFill, CoinslotInteractionStart, LastCoinslotFill, CoinFillCancel, NightSurvived, BuildingRepair, EismolochAppear, EismolochSpawn, ButtonSelect, ButtonApply, ButtonApplyHero, CoinCollect, BuildingStandardProjectile, BallistaProjectile, PlayerSwordBigHit, EnemySpawn, ShowWaveCount, CloseWaveCount, ShowTooltip, None } private static ThronefallAudioManager instance; public readonly float oneshotAudioPoolSize = 15f; public readonly float onshotAudioPoolRecycleTick = 0.3f; private float oneshotSourceRecycleClock; private List oneshotSourcePool = new List(); private OneshotSource bufferOneshotSource; public AudioSet audioContent; public AudioMixerGroup mgMusic; public AudioMixerGroup mgSFX; public AudioMixerGroup mgEnvironment; [HideInInspector] public UnityEvent onBuildingBuild = new UnityEvent(); private bool muted; private float coinslotFillPitch = 1f; private float coinslotFillPitchIncrease = 0.025f; private OneshotSource coinslotFillBackground; private float coinslotFillBackgroundClock; private float coinslotTotalFillTime = 1f; public static ThronefallAudioManager Instance => instance; private void Awake() { if (instance != null) { Object.Destroy(base.gameObject); return; } instance = this; Object.DontDestroyOnLoad(base.gameObject); AudioSource audioSource = null; for (int i = 0; (float)i < oneshotAudioPoolSize; i++) { audioSource = new GameObject("Oneshot Source " + i).AddComponent(); audioSource.transform.SetParent(base.transform); audioSource.rolloffMode = AudioRolloffMode.Linear; audioSource.minDistance = 1f; audioSource.maxDistance = 80f; audioSource.spatialBlend = 0f; oneshotSourcePool.Add(new OneshotSource(audioSource)); } } private void Update() { oneshotSourceRecycleClock += Time.unscaledDeltaTime; if (oneshotSourceRecycleClock > onshotAudioPoolRecycleTick) { RecycleOneshotSources(); } if (coinslotFillBackground != null) { coinslotFillBackgroundClock += Time.deltaTime; coinslotFillBackground.aSource.pitch = Mathf.Lerp(0.75f, 1f, coinslotFillBackgroundClock / coinslotTotalFillTime); } } private void ProcessOneShotEvent(AudioOneShot oneshot, bool worldspace = false, Vector3 position = default(Vector3)) { if (!muted) { switch (oneshot) { case AudioOneShot.CoinslotInteractionStart: coinslotFillPitch = 1f; PlaySoundAsOneShot(audioContent.CoinslotInteractionStart); StopCoinfillBackground(); coinslotFillBackground = PlaySoundAsOneShot(audioContent.PayBackground, 0.2f, 0.75f); break; case AudioOneShot.CoinslotFill: PlaySoundAsOneShot(audioContent.CoinslotFill, 1f, coinslotFillPitch); coinslotFillPitch += coinslotFillPitchIncrease; break; case AudioOneShot.LastCoinslotFill: PlaySoundAsOneShot(audioContent.LastCoinslotFill); StopCoinfillBackground(); break; case AudioOneShot.CoinFillCancel: StopCoinfillBackground(); break; case AudioOneShot.BuildingBuild: onBuildingBuild.Invoke(); PlaySoundAsOneShot(audioContent.BuildingBuild, 1f, Random.RandomRange(0.9f, 1.1f)); break; case AudioOneShot.BuildingUpgrade: PlaySoundAsOneShot(audioContent.BuildingUpgrade); break; case AudioOneShot.NightSurvived: PlaySoundAsOneShot(audioContent.NightSurvived, 0.8f, 1f, null, 0); break; case AudioOneShot.BuildingRepair: PlaySoundAsOneShot(audioContent.BuildingRepair); break; case AudioOneShot.EismolochAppear: PlaySoundAsOneShot(audioContent.EismolochAppear.clips[Random.Range(0, audioContent.EismolochAppear.clips.Length)]); break; case AudioOneShot.EismolochSpawn: PlaySoundAsOneShot(audioContent.EismolochSpawnUnits.clips[Random.Range(0, audioContent.EismolochSpawnUnits.clips.Length)], 1f, 1f, null, 0); break; case AudioOneShot.ButtonSelect: PlaySoundAsOneShot(audioContent.ButtonSelect.GetRandomClip()); break; case AudioOneShot.ButtonApply: PlaySoundAsOneShot(audioContent.ButtonApply.GetRandomClip()); break; case AudioOneShot.ButtonApplyHero: PlaySoundAsOneShot(audioContent.ButtonApplyHero.GetRandomClip()); break; case AudioOneShot.CoinCollect: PlaySoundAsOneShot(audioContent.CoinCollect.GetRandomClip(), 1f, Random.Range(0.9f, 1.1f)); break; case AudioOneShot.BuildingStandardProjectile: PlaySoundAsOneShot(audioContent.TowerShot.GetRandomClip(), 0.5f, Random.Range(0.95f, 1.05f), null, 50, worldspace: true, position); break; case AudioOneShot.BallistaProjectile: PlaySoundAsOneShot(audioContent.BallistaShot.GetRandomClip(), 1f, 1f, null, 30, worldspace: true, position); break; case AudioOneShot.PlayerSwordBigHit: PlaySoundAsOneShot(audioContent.PlayerSwordBigHit); break; case AudioOneShot.EnemySpawn: PlaySoundAsOneShot(audioContent.EnemySpawn, 0.85f, Random.Range(0.95f, 1.05f), null, 140, worldspace: true, position); break; case AudioOneShot.ShowWaveCount: PlaySoundAsOneShot(audioContent.ShowWaveCount, 0.5f); break; case AudioOneShot.CloseWaveCount: PlaySoundAsOneShot(audioContent.CloseWaveCount); break; case AudioOneShot.ShowTooltip: PlaySoundAsOneShot(audioContent.ShowTooltip, 0.3f); break; } } } public OneshotSource PlaySoundAsOneShot(AudioClip clip, float volume = 1f, float pitch = 1f, AudioMixerGroup mixerGroup = null, int priority = 128, bool worldspace = false, Vector3 position = default(Vector3)) { if (mixerGroup == null) { mixerGroup = mgSFX; } bufferOneshotSource = GetFreeOneshotSource(); if (bufferOneshotSource == null) { return null; } if (worldspace) { bufferOneshotSource.aSource.transform.position = position; bufferOneshotSource.aSource.spatialBlend = 1f; } else { bufferOneshotSource.aSource.spatialBlend = 0f; } bufferOneshotSource.aSource.volume = volume; bufferOneshotSource.aSource.pitch = pitch; bufferOneshotSource.aSource.outputAudioMixerGroup = mixerGroup; bufferOneshotSource.aSource.priority = priority; bufferOneshotSource.aSource.PlayOneShot(clip); bufferOneshotSource.available = false; return bufferOneshotSource; } public OneshotSource PlaySoundAsOneShot(AudioSet.ClipArray clips, float volume = 1f, float pitch = 1f, AudioMixerGroup mixerGroup = null, int priority = 128, bool worldspace = false, Vector3 position = default(Vector3)) { if (clips == null) { return null; } if (clips.clips.Length == 0) { return null; } if (mixerGroup == null) { mixerGroup = mgSFX; } bufferOneshotSource = GetFreeOneshotSource(); if (bufferOneshotSource == null) { return null; } if (worldspace) { bufferOneshotSource.aSource.transform.position = position; bufferOneshotSource.aSource.spatialBlend = 1f; } else { bufferOneshotSource.aSource.spatialBlend = 0f; } bufferOneshotSource.aSource.volume = volume; bufferOneshotSource.aSource.pitch = pitch; bufferOneshotSource.aSource.outputAudioMixerGroup = mixerGroup; bufferOneshotSource.aSource.priority = priority; bufferOneshotSource.aSource.PlayOneShot(clips.clips[Random.Range(0, clips.clips.Length)]); bufferOneshotSource.available = false; return bufferOneshotSource; } private OneshotSource GetFreeOneshotSource() { foreach (OneshotSource item in oneshotSourcePool) { if (item.available) { return item; } } return oneshotSourcePool[0]; } private void RecycleOneshotSources() { foreach (OneshotSource item in oneshotSourcePool) { if (!item.aSource.isPlaying) { item.available = true; } } oneshotSourceRecycleClock = 0f; } private void StopCoinfillBackground() { if (coinslotFillBackground != null) { coinslotFillBackground.available = true; coinslotFillBackground.aSource.Stop(); coinslotFillBackground = null; coinslotFillBackgroundClock = 0f; } } public void MakeSureCoinFillSoundIsNotPlayingAnymore() { StopCoinfillBackground(); } public static void Oneshot(AudioOneShot oneshot) { if (instance != null) { instance.ProcessOneShotEvent(oneshot); } else { Debug.LogError("No Audio Manager"); } } public static void WorldSpaceOneShot(AudioOneShot oneshot, Vector3 position) { if (instance != null) { instance.ProcessOneShotEvent(oneshot, worldspace: true, position); } else { Debug.LogError("No Audio Manager"); } } public static void Mute() { instance.muted = true; } public static void Unmute() { instance.muted = false; } public static void SetCoinDisplayFillTime(float time) { instance.coinslotTotalFillTime = time; } }