using System; using System.Collections; using System.Collections.Generic; using Invector.vCamera; using Invector.vCharacterController; using PixelCrushers; using UnityEngine; using UnityEngine.Audio; using Random = UnityEngine.Random; namespace Beyond { [RequireComponent(typeof(AudioSource))] public class MusicManager : Saver { // Start is called before the first frame update public AudioMixer m_audioMixer; [Range(0.05f, 1f)] public float m_targetVolume; public float m_blendTime = 1f; public float m_restTime = 10f; private float m_time = -1f; public enum State { NONE, EXPLORE, COMBAT, CUSTOM, DIALOG }; public State m_state = State.NONE; private State m_prevState = State.NONE; public AudioClip[] m_ExploreClips; public AudioClip[] m_CombatClips; public AudioClip[] m_DialogueClips; public AudioSource m_musicSource; [Tooltip("If music index < 0, then random index is used")] public int m_MusicIndex = -1; private static MusicManager s_instance; private AudioClip m_currentClip; private AudioClip m_previousClip; private bool m_blendSounds = false; public bool shouldPlayRandomClipsFrolList = false; public bool isLocked = false; [Serializable] public class SaveData { public State state; public int musicIndex; } public static MusicManager instance { get { return s_instance; } } private void Awake() { m_musicSource.volume = 0; if (s_instance == null) { s_instance = this; m_musicSource = GetComponent(); m_musicSource.loop = false; UnmuteMusic(); // m_musicSource.volume = m_targetVolume; } else { Debug.LogError("There are two music managers!"); DestroyImmediate(gameObject); } } private void Start() { SetState(m_state); GameStateManager.Instance.m_OnStateChanged.AddListener((GameStateManager.State s) => { if (s == GameStateManager.State.COMBAT) { SetState(State.COMBAT); } else if (s == GameStateManager.State.NORMAL && m_prevState != State.COMBAT) { SetState(m_prevState); } }); } private DayNightSettings dayNightSettings; public void SetState(State state) { if (isLocked) { return; } m_prevState = m_state; AudioClip[] clips = null; ; switch (state) { case State.NONE: break; case State.EXPLORE: clips = m_ExploreClips; break; case State.COMBAT: clips = m_CombatClips; break; case State.DIALOG: clips = m_DialogueClips; break; case State.CUSTOM: break; } m_state = state; if (clips != null && clips.Length > 0) { //get random combat index and return to music that played before on its end if (state == State.COMBAT) { int combatIndex = Random.Range(0, clips.Length); PlayClip(clips[combatIndex]); return; } if (m_MusicIndex < 0) { m_MusicIndex = Random.Range(0, clips.Length); } m_MusicIndex = m_MusicIndex < clips.Length ? m_MusicIndex : clips.Length - 1; PlayClip(clips[m_MusicIndex]); } else { Stop(); } } public void PlayDialogue() { PlayDialogue(-1); } public void PlayDialogue(int idx) { m_MusicIndex = idx; SetState(State.DIALOG); } public void PlayExploration() { PlayExploration(-1); } public void PlayExploration(int idx) { m_MusicIndex = idx; SetState(State.EXPLORE); } public void PlayCombat() { PlayCombat(-1); } public void PlayCombat(int idx) { if (isLocked) { return; } m_MusicIndex = idx; SetState(State.COMBAT); } public void SetPreviousState() { SetState(m_prevState); } public void StopDialogue() { SetState(m_prevState); } public void Stop() { m_musicSource.Stop(); } /* public void OnCombat() { OnCombat(0); } public void OnCombat(int idx) { if (m_combatCtr <= 0) { m_MusicIndex = idx; SetState(State.COMBAT); } m_combatCtr++; } public void OnCombatEnd() { m_combatCtr--; if (m_combatCtr == 0) { SetState(m_prevState); } } */ private IEnumerator PlayCoroutine(AudioClip clip) { m_previousClip = m_currentClip; float volRate = m_targetVolume / m_blendTime; while (m_musicSource.isPlaying) { m_musicSource.volume -= volRate * Time.deltaTime; if (m_musicSource.volume <= 0f) { break; } yield return null; } m_musicSource.clip = clip; m_currentClip = clip; m_musicSource.volume = 0f; m_musicSource.Play(); m_time = 0f; while (m_musicSource.volume < m_targetVolume) { m_musicSource.volume += volRate * Time.deltaTime; yield return null; } m_musicSource.volume = m_targetVolume; //m_musicSource.PlayDelayed(0f); yield return null; } private void PlayClip(AudioClip clip) { //is previous clip playing StopAllCoroutines(); StartCoroutine(PlayCoroutine(clip)); } private float m_savedTargetVolume = 0.5f; /// /// for cutscenes with music in them /// public void MuteMusic() { // m_savedTargetVolume = m_targetVolume; // m_targetVolume = 0f; StopAllCoroutines(); StartCoroutine(DimMusic()); } private IEnumerator DimMusic() { while (m_musicSource.isPlaying) { m_musicSource.volume -= Time.deltaTime; if (m_musicSource.volume <= 0f) { enabled = false; break; } yield return null; } } public void UnmuteMusic() { enabled = true; StopAllCoroutines(); StartCoroutine(TurnOnMusic()); } private IEnumerator TurnOnMusic() { m_musicSource.Play(); while (m_musicSource.volume <= m_targetVolume) { m_musicSource.volume += Time.deltaTime; yield return null; } } /// /// used for night scenery, so entering zones doesnt change current soundtrack /// /// public void PlayLockedMusic(int index) { isLocked = false; m_MusicIndex = index; SetState(State.EXPLORE); isLocked = true; } public void PlayUnlockedExploration(int index) { isLocked = false; m_MusicIndex = index; SetState(State.EXPLORE); } private void OnEnable() { // GameManager.instance.gameTime.m_DayNightEvent.AddListener(OnDayToNight); } private void OnDisable() { // GameManager.instance.gameTime.m_DayNightEvent.RemoveListener(OnDayToNight); } public override string RecordData() { SaveData saveData = new SaveData(); saveData.musicIndex = m_MusicIndex; saveData.state = m_state; return SaveSystem.Serialize(saveData); } public override void ApplyData(string s) { SaveData sd = SaveSystem.Deserialize(s); if (sd != null) { switch (sd.state) { case State.COMBAT: PlayCombat(sd.musicIndex); break; case State.CUSTOM: break; case State.DIALOG: PlayDialogue(sd.musicIndex); break; case State.EXPLORE: PlayExploration(sd.musicIndex); break; } } } private IEnumerator BlendVolume(bool day) { /* m_time = 0f; if (day) { m_daySounds.SetActive(true); } else { m_nightSounds.SetActive(true); } while (m_time < m_blendTime) { float a = m_time / (m_blendTime); float volA = Mathf.Lerp(m_targetVolume, -80f, a); float volB = Mathf.Lerp(-80f, m_targetVolume, a); if (day) { m_dayVolume = volB; m_nightVolume = volA; } else { m_dayVolume = volA; m_nightVolume = volB; } m_audioMixer.SetFloat("DayVolume", m_dayVolume); m_audioMixer.SetFloat("NightVolume", m_nightVolume); m_audioMixer.SetFloat("DayMusicVolume", m_dayVolume); m_audioMixer.SetFloat("NightMusicVolume", m_nightVolume); m_time += Time.deltaTime; yield return null; } if (day) { m_nightSounds.SetActive(false); m_nightMusicSource.enabled = false; } else { m_daySounds.SetActive(false); m_dayMusicSource.enabled = false; } */ yield return null; } private bool CheckIfShouldPlayNext() { if (m_musicSource.isPlaying) return false; if (m_time < m_restTime) { m_time += Time.deltaTime; return false; } return true; } // Update is called once per frame public void Update() { switch (m_state) { case State.EXPLORE: if (CheckIfShouldPlayNext()) { TryToChangeMusicIndex(); PlayExploration(m_MusicIndex); } break; case State.NONE: break; case State.COMBAT: if (CheckIfShouldPlayNext()) { PlayCombat(m_MusicIndex); } break; case State.CUSTOM: break; case State.DIALOG: if (CheckIfShouldPlayNext()) { PlayDialogue(m_MusicIndex); } break; } } private void TryToChangeMusicIndex() { if (shouldPlayRandomClipsFrolList) { m_MusicIndex = Random.Range(0, m_ExploreClips.Length); } } } }