using System.Collections; using UnityEngine; //зависит от ComWrapper, SettingsManager public class SoundManager : MonoBehaviour { public static SoundManager instance; public AudioSource chipLandSound; public AudioSource chipDownSound; public AudioClip down1, down2; public AudioSource VideoAudio; public AudioSource music; public AudioSource wrongSound; public AudioSource winEffect; public AudioSource addCoin; public AudioSource removeCoin; public AudioSource noMoney; public AudioSource explosion; public AudioSource choose; public AudioSource timer; public GameObject switchEffectPrefab; public GameObject Player1Land, Player2Land; // Кешированные длительности клипов private float switchEffectDuration; private float player1LandDuration; private float player2LandDuration; private float effectsVolume; // Кешированные AudioClips для пула private AudioClip switchEffectClip; private AudioClip player1LandClip; private AudioClip player2LandClip; // Пул объектов для звуковых эффектов private const int AUDIO_POOL_SIZE = 12; private GameObject[] audioPool; private int poolIndex = 0; private float musicVolume = 0.5f; private float promoVolume = 0.5f; public void Initialize() { if (instance == null) { instance = this; InitializeAudioPool(); } else { Destroy(gameObject); } try//todo: переделать этот бред ебаный { switchEffectClip = switchEffectPrefab.GetComponent().clip; switchEffectDuration = switchEffectClip.length; player1LandClip = Player1Land.GetComponent().clip; player1LandDuration = player1LandClip.length; player2LandClip = Player2Land.GetComponent().clip; player2LandDuration = player2LandClip.length; PaymentSystem.onCoinAdded += playAddCoin; PaymentSystem.onCoinRemoved += playRemoveCoin; PaymentSystem.OnNotEnoughMoney += playNoMoney; ApplySettings(); SettingsManager.OnSettingsChanged += ApplySettings; } catch { } } private void InitializeAudioPool() { audioPool = new GameObject[AUDIO_POOL_SIZE]; for (int i = 0; i < AUDIO_POOL_SIZE; i++) { audioPool[i] = new GameObject("AudioPoolObject"); audioPool[i].AddComponent(); audioPool[i].SetActive(false); } } private GameObject GetPooledAudioObject() { GameObject obj = audioPool[poolIndex]; poolIndex = (poolIndex + 1) % AUDIO_POOL_SIZE; return obj; } public void ApplySettings() { //print("Применяем настройки звука"); musicVolume = SettingsManager.GetFloat(SettingKey.MUSIC_VOLUME); promoVolume = SettingsManager.GetFloat(SettingKey.PROMO_VOLUME); music.volume = musicVolume; effectsVolume = SettingsManager.GetFloat(SettingKey.SOUNDS_VOLUME); // Массив для оптимизации установки громкости AudioSource[] audioSources = { chipLandSound, chipDownSound, wrongSound, winEffect, addCoin, removeCoin, noMoney, explosion, choose }; foreach (var audioSource in audioSources) { audioSource.volume = effectsVolume; } VideoAudio.volume = promoVolume; } public void SetMusicVolumeToVideo() => VideoAudio.volume = musicVolume; public void SetPromoVolumeToVideo() => VideoAudio.volume = promoVolume; public void playClip(AudioClip clip) { if (clip == null) { Debug.LogWarning("Не установлен звук"); return; } GameObject effect = GetPooledAudioObject(); AudioSource audioSource = effect.GetComponent(); //AudioClip clipToPlay = GameManager.instance.currentPlayer == CellState.Player1 ? down1 : down2; AudioClip clipToPlay = clip; audioSource.clip = clipToPlay; audioSource.pitch = 1; audioSource.volume = effectsVolume; effect.SetActive(true); audioSource.Play(); // Возвращаем в пул через время клипа StartCoroutine(ReturnToPool(effect, clipToPlay.length)); } public void playDropDown() { // Используем пул объектов вместо создания новых GameObject effect = GetPooledAudioObject(); AudioSource audioSource = effect.GetComponent(); //AudioClip clipToPlay = GameManager.instance.currentPlayer == CellState.Player1 ? down1 : down2; AudioClip clipToPlay = down2; audioSource.clip = clipToPlay; //audioSource.pitch = 1 + Random.Range(0, 2) * 0.6f; audioSource.pitch = GameManager.instance.currentPlayer == Team.Player1 ? 1 : 1.3f; audioSource.volume = effectsVolume; effect.SetActive(true); audioSource.Play(); // Возвращаем в пул через время клипа StartCoroutine(ReturnToPool(effect, clipToPlay.length)); } public void playChipBounce() { // Используем пул объектов вместо Instantiate GameObject effect = GetPooledAudioObject(); AudioSource audioSource = effect.GetComponent(); // Выбираем нужный клип и длительность AudioClip clipToPlay = player1LandClip; float duration = player1LandDuration; audioSource.clip = clipToPlay; audioSource.volume = effectsVolume; audioSource.pitch = GameManager.instance.currentPlayer == Team.Player1 ? 0.8f : 0.85f; effect.SetActive(true); audioSource.Play(); // Возвращаем в пул через время клипа StartCoroutine(ReturnToPool(effect, duration)); } public void playSwitch() { // Используем пул объектов вместо Instantiate GameObject effect = GetPooledAudioObject(); AudioSource audioSource = effect.GetComponent(); audioSource.clip = switchEffectClip; audioSource.volume = effectsVolume; audioSource.pitch = 1f; // Сбрасываем pitch для consistency effect.SetActive(true); audioSource.Play(); // Возвращаем в пул через время клипа StartCoroutine(ReturnToPool(effect, switchEffectDuration)); } private IEnumerator ReturnToPool(GameObject obj, float delay) { yield return new WaitForSeconds(delay); obj.SetActive(false); } Coroutine musicCoroutine; public void MusicFade(float fadeDuration, float holdDuration, float targetVolumePercent) { if (musicCoroutine != null) { StopCoroutine(musicCoroutine); } //восстанавливаю громкость float musicVolume = SettingsManager.GetFloat(SettingKey.MUSIC_VOLUME); music.volume = musicVolume; musicCoroutine = StartCoroutine(MusicFadeCoroutine(fadeDuration, holdDuration, targetVolumePercent)); } IEnumerator MusicFadeCoroutine(float fadeDuration, float holdDuration, float targetVolumePercent) { float startVolume = music.volume; float targetVolume = startVolume * Mathf.Clamp01(targetVolumePercent); // Fade to target volume float timer = 0f; while (timer < fadeDuration) { timer += Time.deltaTime; float progress = timer / fadeDuration; music.volume = Mathf.Lerp(startVolume, targetVolume, progress); yield return null; } music.volume = targetVolume; // Ensure exact target volume // Hold at target volume if (holdDuration > 0f) yield return new WaitForSeconds(holdDuration); // Fade back to original volume timer = 0f; while (timer < fadeDuration) { timer += Time.deltaTime; float progress = timer / fadeDuration; music.volume = Mathf.Lerp(targetVolume, startVolume, progress); yield return null; } music.volume = startVolume; // Ensure exact start volume } public void playWrong() => wrongSound.Play(); public void playWin() => winEffect.Play(); public void playAddCoin(int newCount) => addCoin.Play(); public void playRemoveCoin(int newCount) => removeCoin.Play(); public void playNoMoney() => noMoney.Play(); public void playExplosion() => explosion.Play(); public void playChoose() => choose.Play(); public void playTimer() => timer.Play(); }