PJ/Assets/scripts/dotfs_scripts/MANAGER_Music.cs

123 lines
No EOL
3.4 KiB
C#
Executable file

using UnityEngine.Audio;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MANAGER_Music : MonoBehaviour
{
public static MANAGER_Music Instance;
[Header("Main Settings")]
[Range(0f, 1f)]
[SerializeField] private float maxVolume = 0.5f;
[SerializeField] private float fadeDuration = 1.5f;
[Tooltip("Настрой кривую: 0,0 -> 1,1. Плавный выход в начале и конце сделает переход естественнее.")]
[SerializeField] private AnimationCurve fadeCurve = AnimationCurve.Linear(0, 0, 1, 1);
private AudioSource sourceA;
private AudioSource sourceB;
private AudioSource activeSource;
private Coroutine fadeCoroutine;
[Header("Mixer Settings")]
[SerializeField] private AudioMixerGroup musicGroup;
private Dictionary<AudioClip, float> savedPlaybackTimes = new Dictionary<AudioClip, float>();
void Awake()
{
if (Instance == null)
{
Instance = this;
SetupSources();
}
else
{
Destroy(gameObject);
}
}
private void SetupSources()
{
sourceA = gameObject.AddComponent<AudioSource>();
sourceB = gameObject.AddComponent<AudioSource>();
if (musicGroup != null)
{
sourceA.outputAudioMixerGroup = musicGroup;
sourceB.outputAudioMixerGroup = musicGroup;
}
sourceA.loop = sourceB.loop = true;
sourceA.playOnAwake = sourceB.playOnAwake = false;
activeSource = sourceA;
activeSource.volume = 0;
}
public void SwitchMusic(AudioClip newClip)
{
if (activeSource.clip == newClip) return;
AudioSource nextSource = (activeSource == sourceA) ? sourceB : sourceA;
if (fadeCoroutine != null) StopCoroutine(fadeCoroutine);
fadeCoroutine = StartCoroutine(FadeSequence(nextSource, newClip));
}
private IEnumerator FadeSequence(AudioSource nextSource, AudioClip newClip)
{
float t = 0;
float startVol = activeSource.volume;
if (newClip != null)
{
nextSource.clip = newClip;
if (savedPlaybackTimes.TryGetValue(newClip, out float savedTime))
{
nextSource.time = savedTime;
}
else
{
nextSource.time = 0f;
}
nextSource.Play();
}
while (t < fadeDuration)
{
t += Time.deltaTime;
float progress = t / fadeDuration;
float curveValue = fadeCurve.Evaluate(progress);
activeSource.volume = Mathf.Lerp(startVol, 0, curveValue);
if (newClip != null)
nextSource.volume = Mathf.Lerp(0, maxVolume, curveValue);
yield return null;
}
if (activeSource.clip != null)
{
savedPlaybackTimes[activeSource.clip] = activeSource.time;
}
activeSource.Stop();
activeSource.volume = 0;
activeSource = nextSource;
activeSource.volume = maxVolume;
fadeCoroutine = null;
}
public void SetVolume(float volume)
{
maxVolume = Mathf.Clamp01(volume);
if (activeSource != null) activeSource.volume = maxVolume;
}
}