using System; using System.Collections; using UnityEngine; public class SoundManager : MonoBehaviour { public static SoundManager Instance; [Header("Player 1 AudioSources")] public AudioSource player1VoiceSource; public AudioSource player1EffectsSource; [Header("Player 2 AudioSources")] public AudioSource player2VoiceSource; public AudioSource player2EffectsSource; [Header("Общий источник (PvP — оба канала)")] public AudioSource sharedVoiceSource; // pan=0, для PvP голос public AudioSource sharedEffectsSource; // pan=0, для PvP эффекты [Header("Фоновая музыка")] public AudioSource musicSource; public AudioClip[] backgroundMusic; private int currentTrackIndex = -1; private Coroutine musicLoopCoroutine; private bool isMusicCapturedByVideo; [Header("Звуковые эффекты")] public AudioClip[] shootSounds; public AudioClip[] explosionSounds; public AudioClip[] missSounds; private bool isPvPMode = false; private void Awake() { if (Instance == null) Instance = this; else { Destroy(gameObject); return; } DontDestroyOnLoad(gameObject); } private void Start() { ApplyAudioSettings(); StartMusicLoopIfNeeded(); } private void OnEnable() { if (SettingsManager.instance != null) SettingsManager.instance.OnSettingsChanged.AddListener(ApplyAudioSettings); } private void OnDisable() { if (SettingsManager.instance != null) SettingsManager.instance.OnSettingsChanged.RemoveListener(ApplyAudioSettings); } private void ApplyAudioSettings() { float volumeMusic = (float)Convert.ToInt32(SettingsManager.instance.GetSettingValue("Громкость музыки")) / 10f; float volumeEffects = (float)Convert.ToInt32(SettingsManager.instance.GetSettingValue("Громкость эффектов")) / 10f; float volumeVoice = (float)Convert.ToInt32(SettingsManager.instance.GetSettingValue("Громкость голоса")) / 10f; if (musicSource != null) musicSource.volume = volumeMusic; if (player1VoiceSource != null) player1VoiceSource.volume = volumeVoice; if (player1EffectsSource != null) player1EffectsSource.volume = volumeEffects; if (player2VoiceSource != null) player2VoiceSource.volume = volumeVoice; if (player2EffectsSource != null) player2EffectsSource.volume = volumeEffects; if (sharedVoiceSource != null) sharedVoiceSource.volume = volumeVoice; } // ───────────── Музыка ───────────── private void StartMusicLoopIfNeeded() { if (musicLoopCoroutine != null) return; if (backgroundMusic == null || backgroundMusic.Length == 0) return; if (musicSource == null) return; musicLoopCoroutine = StartCoroutine(MusicLoop()); } private void RestartMusicLoop() { if (musicLoopCoroutine != null) { StopCoroutine(musicLoopCoroutine); musicLoopCoroutine = null; } StartMusicLoopIfNeeded(); } private IEnumerator MusicLoop() { while (true) { if (isMusicCapturedByVideo) { yield return null; continue; } PlayNextTrack(); float wait = (musicSource != null && musicSource.clip != null) ? musicSource.clip.length : 1f; yield return new WaitForSeconds(wait); } } private void PlayNextTrack() { if (backgroundMusic.Length == 0 || musicSource == null || isMusicCapturedByVideo) return; int num = UnityEngine.Random.Range(0, backgroundMusic.Length); if (num == currentTrackIndex && backgroundMusic.Length > 1) num = (num + 1) % backgroundMusic.Length; currentTrackIndex = num; musicSource.clip = backgroundMusic[currentTrackIndex]; musicSource.Play(); } public AudioSource CaptureMusicSourceForVideo() { if (musicSource == null) return null; isMusicCapturedByVideo = true; if (musicLoopCoroutine != null) { StopCoroutine(musicLoopCoroutine); musicLoopCoroutine = null; } if (musicSource.isPlaying) musicSource.Stop(); return musicSource; } public void ReleaseMusicSourceFromVideo() { isMusicCapturedByVideo = false; if (musicSource == null || backgroundMusic.Length == 0) return; if (musicSource.isPlaying) musicSource.Stop(); RestartMusicLoop(); } // ───────────── Режим ───────────── public void SetPvPMode(bool pvp) { isPvPMode = pvp; if (sharedVoiceSource != null) sharedVoiceSource.Stop(); } // ───────────── Голос ───────────── public void PlayVoice(int playerId, AudioClip clip) { if (clip == null) return; if (isPvPMode) { if (sharedVoiceSource == null) return; if (sharedVoiceSource.isPlaying) return; sharedVoiceSource.panStereo = 0f; sharedVoiceSource.spatialBlend = 0f; sharedVoiceSource.clip = clip; sharedVoiceSource.Play(); } else { AudioSource src = GetVoiceSource(playerId); if (src == null) return; src.Stop(); ApplyPlayerPan(src, playerId); src.PlayOneShot(clip); } } public void StopVoice(int playerId) { if (isPvPMode) { if (sharedVoiceSource != null) sharedVoiceSource.Stop(); } else { AudioSource src = GetVoiceSource(playerId); if (src != null) src.Stop(); } } // ───────────── Эффекты ───────────── public void PlayShoot(int playerId) { if (shootSounds.Length == 0) return; PlayEffect(playerId, shootSounds[UnityEngine.Random.Range(0, shootSounds.Length)], 0.8f); } public void PlayExplosion(int playerId) { if (explosionSounds.Length == 0) return; PlayEffect(playerId, explosionSounds[UnityEngine.Random.Range(0, explosionSounds.Length)], 1.0f); } public void PlayMiss(int playerId) { if (missSounds.Length == 0) return; PlayEffect(playerId, missSounds[UnityEngine.Random.Range(0, missSounds.Length)], 0.5f); } private void PlayEffect(int playerId, AudioClip clip, float volume) { AudioSource src = GetEffectsSource(playerId); if (src == null) return; ApplyPlayerPan(src, playerId); src.PlayOneShot(clip, volume); } // ───────────── Утилиты ───────────── private void ApplyPlayerPan(AudioSource src, int playerId) { if (src == null) return; src.spatialBlend = 0f; src.panStereo = (playerId == 1) ? -1f : 1f; } private AudioSource GetVoiceSource(int playerId) => playerId == 1 ? player1VoiceSource : player2VoiceSource; private AudioSource GetEffectsSource(int playerId) => playerId == 1 ? player1EffectsSource : player2EffectsSource; }