Files
beyond/Assets/Scripts/Audio/MusicManager.cs
2024-11-20 15:21:28 +01:00

468 lines
13 KiB
C#

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<AudioSource>();
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;
/// <summary>
/// for cutscenes with music in them
/// </summary>
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;
}
}
/// <summary>
/// used for night scenery, so entering zones doesnt change current soundtrack
/// </summary>
/// <param name="index"></param>
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<SaveData>(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);
}
}
}
}