using JetBrains.Annotations; using Marro.PacManUdon; using UnityEngine; public class SoundManager : SyncedObject { [SerializeField] private AudioSource audioSourcePacMan; [SerializeField] private AudioSource audioSourceGhosts; [SerializeField] private AudioSource audioSourceExtraLife; [SerializeField] private AudioClip pacStart; [SerializeField] private AudioClip intermission; [SerializeField] private AudioClip pacDot1; [SerializeField] private AudioClip pacDot2; [SerializeField] private AudioClip pacDie1; [SerializeField] private AudioClip pacFruit; [SerializeField] private AudioClip pacCoin; [SerializeField] private AudioClip pacGhostEat; [SerializeField] private AudioClip pacGhostBlue; [SerializeField] private AudioClip pacGhostRetreat; [SerializeField] private AudioClip pacExtraLife; [SerializeField] private AudioClip siren0; [SerializeField] private AudioClip siren1; [SerializeField] private AudioClip siren2; [SerializeField] private AudioClip siren3; [SerializeField] private AudioClip siren4; private bool alternatePelletSound; private bool ghostRetreating; private bool ghostBlue; private int ghostSoundLevel; private bool currentlyPlayingSiren; private bool suppress; public void Initialize() { Reset(); } public void Reset() { StopAllSound(); alternatePelletSound = false; ghostRetreating = false; ghostBlue = false; ghostSoundLevel = 0; currentlyPlayingSiren = false; suppress = true; } public void SuppressSound(bool suppress) { this.suppress = suppress; if (suppress) { StopAllSound(); } } public void PlayGameStartSound() { PlaySound(audioSourcePacMan, pacStart); } public void StartIntermissionSound() { PlaySound(audioSourcePacMan, intermission, true); } public void PlayPelletSound() { PlaySound(audioSourcePacMan, alternatePelletSound ? pacDot2 : pacDot1); alternatePelletSound = !alternatePelletSound; } public void PlayDeathSound() { PlaySound(audioSourcePacMan, pacDie1); } public void PlayFruitSound() { PlaySound(audioSourcePacMan, pacFruit); } public void PlayCoinSound() { PlaySound(audioSourcePacMan, pacCoin); } public void PlayGhostEatSound() { PlaySound(audioSourcePacMan, pacGhostEat); } public void PlayExtraLifeSound() { PlaySound(audioSourceExtraLife, pacExtraLife); } public void StartGhostSound() { UpdateGhostSound(); } public void SetGhostBlue(bool isBlue) { ghostBlue = isBlue; UpdateGhostSound(); } public void SetGhostRetreat(bool isRetreating) { ghostRetreating = isRetreating; UpdateGhostSound(); } public void StopAllSound() { audioSourcePacMan.Stop(); audioSourceGhosts.Stop(); // audioSourceExtraLife is not stopped on purpose, this sound is never interrupted } public void UpdatePelletCount(int pelletCount) { int level = 0; if (pelletCount < 16) { level = 4; } else if (pelletCount < 32) { level = 3; } else if (pelletCount < 64) { level = 2; } else if (pelletCount < 128) { level = 1; } // Debug.Log($"UpdatePelletCount: {pelletCount}, level: {level}"); if (ghostSoundLevel >= level) { return; } ghostSoundLevel = level; UpdateGhostSound(); } private void PlaySound(AudioSource audioSource, AudioClip audioClip, bool loop = false) { // Debug.Log($"PlaySound, audioSource: {audioSource}, audioClip: {audioClip}, loop: {loop}, suppress: {_suppress}"); if (suppress) { return; } if (loop && audioSource.clip == audioClip && audioSource.isPlaying) { // Don't restart a looping sound return; } audioSource.clip = audioClip; audioSource.Play(); audioSource.loop = loop; } private void SwitchSound(AudioSource audioSource, AudioClip audioClip, bool loop) { if (suppress) { return; } if (!audioSource.isPlaying || audioSource.clip == null) { PlaySound(audioSource, audioClip, loop); } if (audioSource.clip == audioClip) { // No need to switch return; } var newTimeSamples = (int)(audioSource.timeSamples / (double)audioSource.clip.samples * audioClip.samples); audioSource.clip = audioClip; audioSource.timeSamples = newTimeSamples; audioSource.Play(); } private void UpdateGhostSound() { if (ghostRetreating) { PlaySound(audioSourceGhosts, pacGhostRetreat, true); currentlyPlayingSiren = false; return; } if (ghostBlue) { PlaySound(audioSourceGhosts, pacGhostBlue, true); currentlyPlayingSiren = false; return; } var currentGhostLevelSound = GetSoundForGhostLevel(ghostSoundLevel); if (currentlyPlayingSiren) { SwitchSound(audioSourceGhosts, currentGhostLevelSound, true); } else { PlaySound(audioSourceGhosts, currentGhostLevelSound, true); } currentlyPlayingSiren = true; } private AudioClip GetSoundForGhostLevel(int ghostLevel) { switch (ghostLevel) { case 1: return siren1; case 2: return siren2; case 3: return siren3; case 4: return siren4; default: return siren0; }; } public override void CollectSyncedData(byte[] data, ref int index, NetworkEventType eventType) { data.Append(alternatePelletSound, ref index); data.Append(ghostRetreating, ref index); data.Append(ghostBlue, ref index); data.AppendAsByte(ghostSoundLevel, ref index); data.Append(currentlyPlayingSiren, ref index); } public override bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType) { alternatePelletSound = data.ReadBool(ref index); ghostRetreating = data.ReadBool(ref index); ghostBlue = data.ReadBool(ref index); ghostSoundLevel = data.ReadByte(ref index); currentlyPlayingSiren = data.ReadBool(ref index); UpdateGhostSound(); return true; } }