154 lines
4.3 KiB
C#
154 lines
4.3 KiB
C#
|
|
using System.Collections;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace Watermelon
|
|||
|
|
{
|
|||
|
|
[RequireComponent(typeof(AudioSource))]
|
|||
|
|
public class MusicSource : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
private const float DEFAULT_FADE_DURATION = 0.3f;
|
|||
|
|
|
|||
|
|
private static MusicSource defaultMusicSource;
|
|||
|
|
|
|||
|
|
private static MusicSource activeMusicSource;
|
|||
|
|
public static MusicSource ActiveMusicSource => activeMusicSource;
|
|||
|
|
|
|||
|
|
[SerializeField] bool activateAutomatically = false;
|
|||
|
|
|
|||
|
|
private AudioSource audioSource;
|
|||
|
|
public AudioSource AudioSource => audioSource;
|
|||
|
|
|
|||
|
|
// Raw 0–1 volume, independent of global volume and volumeMultiplier
|
|||
|
|
private float currentRawVolume = 0f;
|
|||
|
|
private Coroutine fadeCoroutine;
|
|||
|
|
|
|||
|
|
private float volumeMultiplier = 1.0f;
|
|||
|
|
|
|||
|
|
private bool isInitialized;
|
|||
|
|
|
|||
|
|
private void Start()
|
|||
|
|
{
|
|||
|
|
if(activateAutomatically)
|
|||
|
|
{
|
|||
|
|
Init();
|
|||
|
|
Activate();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Init()
|
|||
|
|
{
|
|||
|
|
if (isInitialized) return;
|
|||
|
|
isInitialized = true;
|
|||
|
|
|
|||
|
|
audioSource = GetComponent<AudioSource>();
|
|||
|
|
audioSource.loop = true;
|
|||
|
|
audioSource.playOnAwake = false;
|
|||
|
|
|
|||
|
|
volumeMultiplier = audioSource.volume;
|
|||
|
|
currentRawVolume = 0f;
|
|||
|
|
audioSource.volume = 0f;
|
|||
|
|
|
|||
|
|
AudioController.VolumeChanged += OnVolumeChanged;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Unload()
|
|||
|
|
{
|
|||
|
|
if (!isInitialized) return;
|
|||
|
|
|
|||
|
|
if (fadeCoroutine != null)
|
|||
|
|
{
|
|||
|
|
StopCoroutine(fadeCoroutine);
|
|||
|
|
fadeCoroutine = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AudioController.VolumeChanged -= OnVolumeChanged;
|
|||
|
|
isInitialized = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnDestroy()
|
|||
|
|
{
|
|||
|
|
Unload();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetAsDefault()
|
|||
|
|
{
|
|||
|
|
defaultMusicSource = this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Activate()
|
|||
|
|
{
|
|||
|
|
if (activeMusicSource == this) return;
|
|||
|
|
|
|||
|
|
if(activeMusicSource != null)
|
|||
|
|
{
|
|||
|
|
activeMusicSource.audioSource.volume = 0.0f;
|
|||
|
|
activeMusicSource.audioSource.Stop();
|
|||
|
|
activeMusicSource.currentRawVolume = 0f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
audioSource.Play();
|
|||
|
|
|
|||
|
|
Fade(1.0f, DEFAULT_FADE_DURATION);
|
|||
|
|
|
|||
|
|
activeMusicSource = this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetVolume(float volume)
|
|||
|
|
{
|
|||
|
|
currentRawVolume = volume;
|
|||
|
|
audioSource.volume = volume * AudioController.GetVolume(AudioType.Music) * volumeMultiplier;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Fade(float targetVolume, float duration, float delay = 0, SimpleCallback onComplete = null)
|
|||
|
|
{
|
|||
|
|
if (fadeCoroutine != null)
|
|||
|
|
StopCoroutine(fadeCoroutine);
|
|||
|
|
|
|||
|
|
fadeCoroutine = StartCoroutine(FadeRoutine(targetVolume, duration, delay, onComplete));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private IEnumerator FadeRoutine(float target, float duration, float delay, SimpleCallback onComplete)
|
|||
|
|
{
|
|||
|
|
if (delay > 0f)
|
|||
|
|
yield return new WaitForSeconds(delay);
|
|||
|
|
|
|||
|
|
float start = currentRawVolume;
|
|||
|
|
float elapsed = 0f;
|
|||
|
|
|
|||
|
|
while (elapsed < duration)
|
|||
|
|
{
|
|||
|
|
elapsed += Time.deltaTime;
|
|||
|
|
currentRawVolume = Mathf.Lerp(start, target, Mathf.Clamp01(elapsed / duration));
|
|||
|
|
audioSource.volume = currentRawVolume * AudioController.GetVolume(AudioType.Music) * volumeMultiplier;
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
currentRawVolume = target;
|
|||
|
|
audioSource.volume = currentRawVolume * AudioController.GetVolume(AudioType.Music) * volumeMultiplier;
|
|||
|
|
|
|||
|
|
fadeCoroutine = null;
|
|||
|
|
onComplete?.Invoke();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnVolumeChanged(AudioType audioType, float volume)
|
|||
|
|
{
|
|||
|
|
if (audioType != AudioType.Music) return;
|
|||
|
|
|
|||
|
|
audioSource.volume = currentRawVolume * volume * volumeMultiplier;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool IsActive()
|
|||
|
|
{
|
|||
|
|
return activeMusicSource == this;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void ActivateDefault()
|
|||
|
|
{
|
|||
|
|
if (activeMusicSource == defaultMusicSource) return;
|
|||
|
|
|
|||
|
|
if (defaultMusicSource != null)
|
|||
|
|
defaultMusicSource.Activate();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|