using Cysharp.Threading.Tasks; using System.Threading; using UnityEngine; using UnityEngine.Audio; public class MixerController : MonoBehaviour { const string LowpassCutoffFreq = "LowpassCutoffFreq"; const string LowpassResonance = "LowpassResonance"; [SerializeField] AudioMixer mixer; [Header("Фильтры над водой")] [SerializeField] float upCutoff = 22000f; [SerializeField] float upResonance = 1f; [SerializeField] float upSpeed = 0.5f; [Header("Фильтры под водой")] [SerializeField] float downCutoff = 1000f; [SerializeField] float downResonance = 2f; [SerializeField] float downSpeed = 1.5f; private CancellationTokenSource cts; private bool initialized = false; private float t = 1; public void Init() { G.PlayerStateModel.PlayerComponent.DiveSystem.Dived += DiveSystem_Dived; G.PlayerStateModel.PlayerComponent.DiveSystem.Surfaced += DiveSystem_Surfaced; mixer.SetFloat(LowpassCutoffFreq, upCutoff); mixer.SetFloat(LowpassResonance, upResonance); initialized = true; } private void DiveSystem_Surfaced() => SetUnderwater(goingDown: false); private void DiveSystem_Dived() => SetUnderwater(goingDown: true); public void SetUnderwater(bool goingDown) { cts?.Cancel(); cts?.Dispose(); cts = new(); var speed = goingDown ? downSpeed : upSpeed; SetFiltersAsync(goingDown, speed, cts.Token).Forget(); } private async UniTask SetFiltersAsync(bool goingDown, float speed, CancellationToken token) { float targetT = goingDown ? 0 : 1; while(t != targetT && !token.IsCancellationRequested) { float delta = Time.deltaTime * speed; t = Mathf.MoveTowards(t, targetT, delta); var cutoff = Mathf.Lerp(downCutoff, upCutoff, t); var resonance = Mathf.Lerp(downResonance, upResonance, t); mixer.SetFloat(LowpassCutoffFreq, cutoff); mixer.SetFloat(LowpassResonance, resonance); await UniTask.Yield(PlayerLoopTiming.Update, token); } } private void OnDestroy() { cts?.Cancel(); cts?.Dispose(); mixer.SetFloat(LowpassCutoffFreq, upCutoff); mixer.SetFloat(LowpassResonance, upResonance); if(initialized) { G.PlayerStateModel.PlayerComponent.DiveSystem.Dived -= DiveSystem_Dived; G.PlayerStateModel.PlayerComponent.DiveSystem.Surfaced -= DiveSystem_Surfaced; } } }