using System.Collections; using UnityEngine; namespace Management { /// /// Singleton pattern object that holds an audio source, designed as single source of /// truth and driver for the BGM music. /// [RequireComponent(typeof(AudioSource))] public class BGM : MonoBehaviour { // hold a static reference to enforce singleton pattern private static BGM _instance; // the audiosource that will play the music private AudioSource _audioSource; // get the original volume set in the editor so when we fade in/out we know // what volume to return to. private float _originalVolume; // 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(AudioClip clip, float t = 1f) { if (clip == null) { Debug.LogWarning("BGM: Selected clip is null"); return; } StopAllCoroutines(); if (t <= 0) { _audioSource.Stop(); _audioSource.clip = clip; _audioSource.Play(); _audioSource.volume = _originalVolume; } else { StartCoroutine(FadeInRoutine(clip, t)); } } private IEnumerator FadeInRoutine(AudioClip clip, float t) { var timer = 0f; var startVolume = _audioSource.volume; var fadeInTarget = _audioSource.isPlaying ? t / 2f : t; if (_audioSource.isPlaying) { while (timer < t / 2f) { timer += Time.deltaTime; _audioSource.volume = Mathf.Lerp(startVolume, 0f, timer / (t / 2f)); yield return null; } _audioSource.volume = 0f; timer = 0f; } _audioSource.Stop(); _audioSource.clip = clip; _audioSource.Play(); while (timer < fadeInTarget) { timer += Time.deltaTime; _audioSource.volume = Mathf.Lerp(0f, _originalVolume, timer / fadeInTarget); yield return null; } _audioSource.volume = _originalVolume; } private void Awake() { // enforce singleton if (_instance != null && _instance != this) { Destroy(gameObject); return; } _instance = this; _audioSource = GetComponent(); _originalVolume = _audioSource.volume; DontDestroyOnLoad(gameObject); } } }