sea-battle/Assets/Scripts/SoundManager.cs

249 lines
7.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}