sea-battle-vr/Assets/Scripts/Menu/MenuAnimation.cs

164 lines
5.2 KiB
C#

using Cysharp.Threading.Tasks;
using System;
using System.Threading;
using UnityEngine;
public class MenuAnimation : MonoBehaviour
{
[Header("Группы")]
[SerializeField] private CanvasGroup beforePaymentGroup;
[SerializeField] private CanvasGroup afterPaymentGroup;
[SerializeField] private float switchSpeed = 4;
[SerializeField] private float stayDelay = 2;
[Header("Инструкция")]
[SerializeField] private CanvasGroup startInstruction;
[Header("Инструкция перископ")]
[SerializeField] private CanvasGroup periscopeInstruction;
[SerializeField] private Transform periscopeTransform;
[SerializeField] private float upPosition = 100;
[SerializeField] private float downPosition = -50;
[SerializeField] private AnimationCurve curve;
[SerializeField] private CanvasGroup upGroup;
[SerializeField] private CanvasGroup downGroup;
[Header("Градиент")]
[SerializeField] private CanvasGroup gradient;
[SerializeField] private float gradientTransitionSpeed = 2;
private CancellationTokenSource cts;
private bool payed = false;
public void Init(bool alreadyPayed)
{
beforePaymentGroup.alpha = alreadyPayed ? 0f : 1f;
afterPaymentGroup.alpha = alreadyPayed ? 1 : 0f;
gradient.alpha = alreadyPayed ? 1f : 0f;
startInstruction.alpha = 0;
periscopeInstruction.alpha = 1;
upGroup.alpha = 0;
downGroup.alpha = 0;
if (alreadyPayed)
{
payed = true;
StartInstructionAnimation();
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
WalletManager.ResetBalance();
}
}
private void OnDestroy() => StopAnimation();
private void StopAnimation()
{
cts?.Cancel();
cts?.Dispose();
cts = null;
}
public void PerformTransition()
{
if(payed) return;
StopAnimation();
cts = new CancellationTokenSource();
Transition(cts.Token).Forget();
}
private async UniTask Transition(CancellationToken ct)
{
await TransitionToInstruction(ct);
if (!ct.IsCancellationRequested)
{
await InstructionAnimation(ct);
}
}
public void StartInstructionAnimation()
{
StopAnimation();
cts = new CancellationTokenSource();
InstructionAnimation(cts.Token).Forget();
}
private async UniTask TransitionToInstruction(CancellationToken ct)
{
LerpAlpha(0, 1, gradientTransitionSpeed, gradient, ct).Forget();
await LerpAlpha(1, 0, switchSpeed, beforePaymentGroup, ct);
await LerpAlpha(0, 1, switchSpeed, afterPaymentGroup, ct);
}
private async UniTask InstructionAnimation(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await InstructionPeriscope(ct);
await UniTask.Delay(TimeSpan.FromSeconds(stayDelay / 4), cancellationToken: ct);
await InstructionStart(ct);
await UniTask.Delay(TimeSpan.FromSeconds(stayDelay / 4), cancellationToken: ct);
}
}
private async UniTask InstructionPeriscope(CancellationToken ct)
{
downGroup.alpha = 0;
upGroup.alpha = 1;
LerpAlpha(0, 1, switchSpeed, periscopeInstruction, ct).Forget();
await MoveLocalY(upPosition, switchSpeed/2, periscopeTransform, curve, ct);
await UniTask.Delay(TimeSpan.FromSeconds(stayDelay/2), cancellationToken: ct);
await LerpAlpha(1, 0, switchSpeed*2, upGroup, ct);
LerpAlpha(0, 1, switchSpeed*2, downGroup, ct).Forget();
await MoveLocalY(0, switchSpeed/2, periscopeTransform, curve, ct);
LerpAlpha(1, 0, switchSpeed, periscopeInstruction, ct).Forget();
await UniTask.Delay(TimeSpan.FromSeconds(stayDelay/2), cancellationToken: ct);
}
private async UniTask InstructionStart(CancellationToken ct)
{
await LerpAlpha(0, 1, switchSpeed, startInstruction, ct);
await UniTask.Delay(TimeSpan.FromSeconds(stayDelay), cancellationToken: ct);
await LerpAlpha(1, 0, switchSpeed, startInstruction, ct);
}
private async UniTask LerpAlpha(float from, float to, float speed, CanvasGroup cg, CancellationToken ct)
{
float t = 0;
while (t < 1 && !ct.IsCancellationRequested)
{
t += Time.deltaTime * speed;
t = Mathf.Min(t, 1);
cg.alpha = Mathf.Lerp(from, to, t);
await UniTask.Yield(ct);
}
cg.alpha = to;
}
private async UniTask MoveLocalY(float targetY, float speed, Transform transform, AnimationCurve curve, CancellationToken ct)
{
float t = 0;
float startY = transform.localPosition.y;
while (!ct.IsCancellationRequested && t < 1)
{
t += Time.deltaTime * speed;
t = Mathf.Min(t, 1);
float t1 = curve.Evaluate(t);
transform.localPosition = new Vector2(transform.localPosition.x, Mathf.Lerp(startY, targetY, t1));
await UniTask.Yield(ct);
}
transform.localPosition = new Vector2(transform.localPosition.x, targetY);
}
}