116 lines
3.4 KiB
C#

using System.Collections;
using UnityEngine;
namespace Management
{
/// <summary>
/// Singleton pattern object that holds an audio source, designed as single source of
/// truth and driver for the BGM music.
/// </summary>
public class BGM : MonoBehaviour
{
public enum TrackType
{
Core,
Muted,
March,
Victory
}
private TrackType _currentlyPlaying = TrackType.Muted;
// hold a static reference to enforce singleton pattern
private static BGM _instance;
// the audiosource that will play the music
[SerializeField] private AudioSource[] audioSources;
[SerializeField] private AudioSource menuSource;
public void MenuToGameMusic()
{
StartCoroutine(MenuToGameMusicRoutine());
}
private IEnumerator MenuToGameMusicRoutine()
{
var t = 1f;
var timer = 0f;
foreach(var a in audioSources)
{
a.Play();
}
while (timer < t)
{
timer += Time.deltaTime;
menuSource.volume = Mathf.Lerp(1, 0, timer / t);
yield return null;
}
timer = 0;
_currentlyPlaying = TrackType.Muted;
while (timer < t)
{
timer += Time.deltaTime;
audioSources[0].volume = Mathf.Lerp(0, 1, timer / t);
yield return null;
}
}
// Fades out the currently playing music if playing, then fades in
// the provided clip over the amount of time specified.
// if t == 0 swap is instant.
public void FadeIn(TrackType type, float t = 0.5f)
{
if (type == _currentlyPlaying) return;
StopAllCoroutines();
var currentAudioSource = _currentlyPlaying switch
{
TrackType.Muted => audioSources[0],
TrackType.Core => audioSources[1],
TrackType.March => audioSources[2],
_ => audioSources[0],
};
var targetAudioSource = type switch
{
TrackType.Muted => audioSources[0],
TrackType.Core => audioSources[1],
TrackType.March => audioSources[2],
_ => audioSources[0],
};
StartCoroutine(FadeInRoutine(currentAudioSource, targetAudioSource, t));
_currentlyPlaying = type;
}
private IEnumerator FadeInRoutine(AudioSource current, AudioSource target, float t)
{
var timer = 0f;
while (timer < t)
{
timer += Time.deltaTime;
current.volume = Mathf.Lerp(1, 0, timer / t);
target.volume = Mathf.Lerp(0, 1, timer / t);
yield return null;
}
current.volume = 0;
target.volume = 1;
}
private void Awake()
{
// enforce singleton
if (_instance != null && _instance != this)
{
Destroy(gameObject);
return;
}
_instance = this;
DontDestroyOnLoad(gameObject);
}
}
}