Обновить игровые системы и удалить устаревший код

This commit is contained in:
Сергей Бондарь 2026-08-28 13:43:05 +03:00
parent a656816fce
commit 16847fedf3
16 changed files with 374 additions and 1768 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,306 +1,129 @@
using DG.Tweening;
using System.Collections;
using DG.Tweening;
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;
[SerializeField] private AudioSource _musicSource;
[SerializeField] private AudioSource _sfxSource;
private Tween _musicFadeTween;
private Coroutine _musicDuckCoroutine;
public float MusicVolume { get; private set; } = 0.5f;
public float PromoVolume { get; private set; } = 0.5f;
public void FadeMusic(bool enable, float duration)
private void OnDestroy()
{
float targetVolume = enable ? MusicVolume : 0;
music.DOFade(targetVolume, duration).PlayForward();
if (instance != this)
return;
SettingsManager.OnSettingsChanged -= ApplySettings;
_musicFadeTween?.Kill();
instance = null;
}
public void Initialize()
{
if (instance == null)
{
instance = this;
InitializeAudioPool();
}
else
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
//switchEffectClip = switchEffectPrefab.GetComponent<AudioSource>().clip;
//switchEffectDuration = switchEffectClip.length;
//player1LandClip = Player1Land.GetComponent<AudioSource>().clip;
//player1LandDuration = player1LandClip.length;
//player2LandClip = Player2Land.GetComponent<AudioSource>().clip;
//player2LandDuration = player2LandClip.length;
PaymentSystem.onCoinAdded += playAddCoin;
PaymentSystem.onCoinRemoved += playRemoveCoin;
PaymentSystem.OnNotEnoughMoney += playNoMoney;
instance = this;
ApplySettings();
SettingsManager.OnSettingsChanged -= ApplySettings;
SettingsManager.OnSettingsChanged += ApplySettings;
if (_musicSource.clip != null && _musicSource.isPlaying == false)
_musicSource.Play();
}
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<AudioSource>();
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;
_musicSource.volume = MusicVolume;
_sfxSource.volume = SettingsManager.GetFloat(SettingKey.SOUNDS_VOLUME);
}
public void SetMusicVolumeToVideo() => VideoAudio.volume = MusicVolume;
public void SetPromoVolumeToVideo() => VideoAudio.volume = PromoVolume;
public void PlaySfx(AudioClip clip)
=> PlaySfx(clip, 1f);
public void playClip(AudioClip clip)
public void PlaySfx(AudioClip clip, float relativeVolume)
{
if (clip == null)
{
Debug.LogWarning("Не установлен звук");
return;
}
GameObject effect = GetPooledAudioObject();
AudioSource audioSource = effect.GetComponent<AudioSource>();
//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));
_sfxSource.PlayOneShot(clip, Mathf.Max(0f, relativeVolume));
}
public void playClip(AudioClip clip, float volume)
public void FadeMusic(bool enable, float duration)
{
if (clip == null)
{
Debug.LogWarning("Не установлен звук");
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;
}
GameObject effect = GetPooledAudioObject();
AudioSource audioSource = effect.GetComponent<AudioSource>();
//AudioClip clipToPlay = GameManager.instance.currentPlayer == CellState.Player1 ? down1 : down2;
AudioClip clipToPlay = clip;
audioSource.clip = clipToPlay;
audioSource.pitch = 1;
audioSource.volume = effectsVolume * volume;
effect.SetActive(true);
audioSource.Play();
// Возвращаем в пул через время клипа
StartCoroutine(ReturnToPool(effect, clipToPlay.length));
}
public void playDropDown()
{
// Используем пул объектов вместо создания новых
GameObject effect = GetPooledAudioObject();
AudioSource audioSource = effect.GetComponent<AudioSource>();
//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<AudioSource>();
// Выбираем нужный клип и длительность
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));
StopCoroutine(_musicDuckCoroutine);
_musicDuckCoroutine = null;
}
public void playSwitch()
private IEnumerator DuckMusicCoroutine(
float fadeDuration,
float holdDuration,
float targetVolumePercent)
{
// Используем пул объектов вместо Instantiate
GameObject effect = GetPooledAudioObject();
AudioSource audioSource = effect.GetComponent<AudioSource>();
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 startVolume = MusicVolume;
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
yield return FadeMusicVolume(startVolume, targetVolume, fadeDuration);
// 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
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;
}
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();
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;
}
}

View File

@ -112,7 +112,7 @@ namespace CharacterSystem
if (SoundManager.instance != null)
{
SoundManager.instance.MusicFade(
SoundManager.instance.DuckMusic(
fadeDuration: 0.2f,
holdDuration: Mathf.Max(replica.clip.length - 0.2f, 0f),
targetVolumePercent: 0.5f);

View File

@ -101,7 +101,7 @@ namespace CharacterSystem
}
public void InvokeThrowChip()
=> SoundManager.instance.playClip(chipThrowClip);
=> SoundManager.instance.PlaySfx(chipThrowClip);
public void ResetModule()
{

View File

@ -8,6 +8,9 @@ public class CoinCounter : MonoBehaviour
public CanvasGroup balanceSignGroup;
[SerializeField] private CanvasGroup _notEnoughSignGroup;
[SerializeField] private RectTransform _notEnoughSign;
[SerializeField] private AudioClip _coinAddedSound;
[SerializeField] private AudioClip _coinRemovedSound;
[SerializeField] private AudioClip _notEnoughMoneySound;
private bool _initialized;
private Sequence _notEnoughSequence;
@ -71,8 +74,15 @@ public class CoinCounter : MonoBehaviour
_notEnoughSequence.SetLoops(flashesCount);
_notEnoughSequence.OnComplete(ResetNotEnoughSign);
_notEnoughSequence.PlayForward();
SoundManager.instance.PlaySfx(_notEnoughMoneySound);
}
private void PlayCoinAddedSound(int amount)
=> SoundManager.instance.PlaySfx(_coinAddedSound);
private void PlayCoinRemovedSound(int amount)
=> SoundManager.instance.PlaySfx(_coinRemovedSound);
private void StopNotEnoughAnimation()
{
_notEnoughSequence?.Kill();
@ -90,6 +100,8 @@ public class CoinCounter : MonoBehaviour
{
Unsubscribe();
PaymentSystem.OnBalanceChanged += UpdateBalanceLabel;
PaymentSystem.onCoinAdded += PlayCoinAddedSound;
PaymentSystem.onCoinRemoved += PlayCoinRemovedSound;
PaymentSystem.OnNotEnoughMoney += PlayNotEnoughAnimation;
SettingsManager.OnSettingsChanged += UpdateBalanceLabelBySettings;
}
@ -97,6 +109,8 @@ public class CoinCounter : MonoBehaviour
private void Unsubscribe()
{
PaymentSystem.OnBalanceChanged -= UpdateBalanceLabel;
PaymentSystem.onCoinAdded -= PlayCoinAddedSound;
PaymentSystem.onCoinRemoved -= PlayCoinRemovedSound;
PaymentSystem.OnNotEnoughMoney -= PlayNotEnoughAnimation;
SettingsManager.OnSettingsChanged -= UpdateBalanceLabelBySettings;
}

View File

@ -7,6 +7,7 @@ using UnityEngine;
public class Board : MonoBehaviour
{
[SerializeField] private ChipPointer pointer;
[SerializeField] private AudioClip _clearSound;
[Header("PvP colors")]
[SerializeField] private Color _pvpInnerColor = new Color(0.2f, 0.65f, 1f, 1f);
@ -116,7 +117,7 @@ public class Board : MonoBehaviour
private void PerformChipsClear()
{
SoundManager.instance.playExplosion();
SoundManager.instance.PlaySfx(_clearSound);
GameManager.Instance.currentChip?.RemoveFromField();
if (Grid == null) return;

View File

@ -1,75 +1,70 @@
using TMPro;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
public class Timer : MonoBehaviour
{
[SerializeField] private float restTime;
private bool processing = false;
public TextMeshProUGUI TimeLabel;
private bool recentlyPlayed = false;
private float lastSignalTime = 0;
public UnityEvent OnTimerEnded;
[FormerlySerializedAs("TimeLabel")] public TextMeshProUGUI timeLabel;
void Update()
[SerializeField, FormerlySerializedAs("restTime")] private float _restTime;
[SerializeField] private AudioClip _warningSound;
private bool _processing;
private bool _recentlyPlayed;
private float _lastSignalTime;
private void Update()
{
if (processing)
if (_processing == false)
return;
UiDraw();
_restTime -= Time.deltaTime;
if (_restTime <= 0f)
{
UiDraw();
restTime -= Time.deltaTime;
if (restTime <= 0)
{
restTime = 0;
StopTimer();
OnTimerEnded?.Invoke();
}
int rest = (int)restTime;
if (!recentlyPlayed && (rest % 60 == 0 || rest == 30 || rest < 11))
{
SoundManager.instance.playTimer();
recentlyPlayed = true;
lastSignalTime = Time.time;
}
if (recentlyPlayed)
{
if (Time.time - lastSignalTime >= 1f)
{
recentlyPlayed = false;
}
}
_restTime = 0f;
StopTimer();
OnTimerEnded?.Invoke();
}
int rest = (int)_restTime;
if (_recentlyPlayed == false && (rest % 60 == 0 || rest == 30 || rest < 11))
{
SoundManager.instance.PlaySfx(_warningSound);
_recentlyPlayed = true;
_lastSignalTime = Time.time;
}
if (_recentlyPlayed && Time.time - _lastSignalTime >= 1f)
_recentlyPlayed = false;
}
public void SetupTimer(float seconds)
{
restTime = seconds;
_restTime = seconds;
UiDraw();
}
public void StartTimer()
{
processing = true;
}
=> _processing = true;
public void StopTimer()
{
processing = false;
}
void UiDraw()
{
string minutes = ((int)(restTime / 60)).ToString();
string seconds = ((int)(restTime % 60)).ToString();
=> _processing = false;
if (minutes.Length < 2) minutes = "0" + minutes;
if (seconds.Length < 2) seconds = "0" + seconds;
private void UiDraw()
{
string minutes = ((int)(_restTime / 60)).ToString();
string seconds = ((int)(_restTime % 60)).ToString();
string result = minutes + ":" + seconds;
TimeLabel.text = result;
if (minutes.Length < 2)
minutes = "0" + minutes;
if (seconds.Length < 2)
seconds = "0" + seconds;
timeLabel.text = minutes + ":" + seconds;
}
}
}

View File

@ -35,6 +35,9 @@ public class VideoUtility : MonoBehaviour
PlayEnding();
}
private void OnDestroy()
=> SettingsManager.OnSettingsChanged -= ApplyAudioSettings;
public void Initialize()
{
if (_instance == null)
@ -43,6 +46,9 @@ public class VideoUtility : MonoBehaviour
ConfigureBackgroundPlayer(_primaryPlayer);
ConfigureBackgroundPlayer(_secondaryPlayer);
_activeBackgroundPlayer = _primaryPlayer;
ApplyAudioSettings();
SettingsManager.OnSettingsChanged -= ApplyAudioSettings;
SettingsManager.OnSettingsChanged += ApplyAudioSettings;
PlayBackgroundImmediately(_menuBackground);
}
@ -187,4 +193,7 @@ public class VideoUtility : MonoBehaviour
_audioSource.Play();
_primaryPlayer.Play();
}
private void ApplyAudioSettings()
=> _audioSource.volume = SettingsManager.GetFloat(SettingKey.PROMO_VOLUME);
}

View File

@ -148,7 +148,7 @@ public class NotificationSystem : MonoBehaviour
}
//подождать
SoundManager.instance.playClip(notification.audioClip);
SoundManager.instance.PlaySfx(notification.audioClip);
yield return new WaitForSeconds(standTime);
//#ЗАДВИНУТЬ ВНИЗ

View File

@ -148,7 +148,7 @@ namespace PrizeSystem
else
{
SetPrizingError(true);
SoundManager.instance.playClip(prizeErrorSound);
SoundManager.instance.PlaySfx(prizeErrorSound);
}
}
if (atLeastOnePrize)
@ -208,7 +208,7 @@ namespace PrizeSystem
int random = UnityEngine.Random.Range(0, PrizeNotificationSounds.Count);
AudioClip notification = PrizeNotificationSounds[random];
SoundManager.instance.playClip(notification);
SoundManager.instance.PlaySfx(notification);
}
public static Sprite GetPrizeIcon(PrizeType prizeType)

View File

@ -19,7 +19,7 @@ public class PrizeButton : MSignalButton
_animation.AppendCallback(() =>
{
OnPrize?.Invoke(_prizeType);
SoundManager.instance.playClip(_clip);
SoundManager.instance.PlaySfx(_clip);
});
_animation.PlayForward();

View File

@ -41,7 +41,7 @@ public class MSignalButton : MonoBehaviour
_animation.AppendCallback(() =>
{
OnClick?.Invoke();
SoundManager.instance.playClip(_clip);
SoundManager.instance.PlaySfx(_clip);
});
_animation.PlayForward();
@ -73,4 +73,4 @@ public class MSignalButton : MonoBehaviour
_animation = null;
}
}
}
}

View File

@ -33,7 +33,7 @@ public class MToggle : MonoBehaviour
public void SetValue(bool value)
{
Value = value;
SoundManager.instance.playClip(value ? EnableSound : DisableSound);
SoundManager.instance.PlaySfx(value ? EnableSound : DisableSound);
StopAnimation();
_animation = GetAnimation(value);
@ -75,4 +75,4 @@ public class MToggle : MonoBehaviour
_animation.Kill();
_animation = null;
}
}
}

View File

@ -142,7 +142,7 @@ public class SettingFunctions : MonoBehaviour
if (replica == null)
continue;
SoundManager.instance.playClip(replica);
SoundManager.instance.PlaySfx(replica);
return;
}
@ -168,7 +168,7 @@ public class SettingFunctions : MonoBehaviour
_activeQrTestPanel = null;
if (SoundManager.instance != null)
SoundManager.instance.playClip(_qrTestUnavailableClip);
SoundManager.instance.PlaySfx(_qrTestUnavailableClip);
return;
}

View File

@ -20,7 +20,7 @@ public class StringView : BaseSettingView
private void _stepper_OnValueChanged(string newValue)
{
CachedSetting.StringValue = newValue;
SoundManager.instance.playClip(SwitchClip);
SoundManager.instance.PlaySfx(SwitchClip);
SettingsManager.TriggerSettingsChanged();
}
}
}

View File

@ -29,7 +29,7 @@ public class Promo : MonoBehaviour, IControlable
{
KillActiveAnimation();
ControlsEnabled = true;
_audioSource.volume = SoundManager.instance.PromoVolume;
_audioSource.volume = SettingsManager.GetFloat(SettingKey.PROMO_VOLUME);
_panel.gameObject.SetActive(true);
_videoPlayer.Play();
_videoPlayer.loopPointReached += VideoEnded;
@ -85,4 +85,4 @@ public class Promo : MonoBehaviour, IControlable
if (In.AnyButton())
_menuPromoTransit.GotoMenu();
}
}
}