using System.Collections; using DG.Tweening; using UnityEngine; public class SoundManager : MonoBehaviour { public static SoundManager instance; [SerializeField] private AudioSource _musicSource; [SerializeField] private AudioSource _sfxSource; [SerializeField] private AudioClip _columnSelectionClip; private Tween _musicFadeTween; private Coroutine _musicDuckCoroutine; public float MusicVolume { get; private set; } = 0.5f; private void OnDestroy() { if (instance != this) return; SettingsManager.OnSettingsChanged -= ApplySettings; _musicFadeTween?.Kill(); instance = null; } public void Initialize() { if (instance != null && instance != this) { Destroy(gameObject); return; } instance = this; ApplySettings(); SettingsManager.OnSettingsChanged -= ApplySettings; SettingsManager.OnSettingsChanged += ApplySettings; if (_musicSource.clip != null && _musicSource.isPlaying == false) _musicSource.Play(); } public void ApplySettings() { MusicVolume = SettingsManager.GetFloat(SettingKey.MUSIC_VOLUME); _musicSource.volume = MusicVolume; _sfxSource.volume = SettingsManager.GetFloat(SettingKey.SOUNDS_VOLUME); } public void PlaySfx(AudioClip clip) => PlaySfx(clip, 1f); public void PlaySfx(AudioClip clip, float relativeVolume) { if (clip == null) { Debug.LogWarning("Не установлен звук"); return; } _sfxSource.PlayOneShot(clip, Mathf.Max(0f, relativeVolume)); } public void PlayColumnSelectionSound() { if (_columnSelectionClip != null) PlaySfx(_columnSelectionClip); } public void FadeMusic(bool enable, float duration) { StopMusicTransitions(); float targetVolume = enable ? MusicVolume : 0f; _musicFadeTween = _musicSource.DOFade(targetVolume, duration); _musicFadeTween.PlayForward(); } public void DuckMusic(float fadeDuration, float holdDuration, float targetVolumePercent) { StopMusicTransitions(); _musicDuckCoroutine = StartCoroutine( DuckMusicCoroutine(fadeDuration, holdDuration, targetVolumePercent)); } private void StopMusicTransitions() { _musicFadeTween?.Kill(); _musicFadeTween = null; if (_musicDuckCoroutine == null) return; StopCoroutine(_musicDuckCoroutine); _musicDuckCoroutine = null; } private IEnumerator DuckMusicCoroutine( float fadeDuration, float holdDuration, float targetVolumePercent) { float startVolume = MusicVolume; float targetVolume = startVolume * Mathf.Clamp01(targetVolumePercent); yield return FadeMusicVolume(startVolume, targetVolume, fadeDuration); if (holdDuration > 0f) yield return new WaitForSeconds(holdDuration); yield return FadeMusicVolume(targetVolume, MusicVolume, fadeDuration); _musicDuckCoroutine = null; } private IEnumerator FadeMusicVolume(float startVolume, float targetVolume, float duration) { if (duration <= 0f) { _musicSource.volume = targetVolume; yield break; } float elapsedTime = 0f; while (elapsedTime < duration) { elapsedTime += Time.deltaTime; float progress = Mathf.Clamp01(elapsedTime / duration); _musicSource.volume = Mathf.Lerp(startVolume, targetVolume, progress); yield return null; } _musicSource.volume = targetVolume; } }