diff --git a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/GameManager.cs b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/GameManager.cs index 25a0dabf..1c1c52df 100644 --- a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/GameManager.cs +++ b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/GameManager.cs @@ -32,6 +32,7 @@ namespace MyGame.Scenes.MiniGame.Scripts [SerializeField] private ResultManager resultManager; [SerializeField] private GameObject readyObject; [SerializeField] private GameObject tutorialPopupObject; + [SerializeField] private float resultWaitTime = 1f; #if UNITY_EDITOR [SerializeField] private bool isDebug; #endif @@ -214,6 +215,11 @@ namespace MyGame.Scenes.MiniGame.Scripts player.SetSpeed(x); }).AddTo(this); + player.OnEndHit.Subscribe(_ => + { + state.Value = GameState.Success; + }).AddTo(this); + player.OnHitItem.Where(_ => state.Value == GameState.Play).Subscribe(x => { if (!x.TryGetComponent(out var item)) @@ -264,11 +270,6 @@ namespace MyGame.Scenes.MiniGame.Scripts } player.Hit(x.ClosestPoint(playerTransform.position)); x.enabled = false; - // ゲーム終了 - Observable.Timer(TimeSpan.FromSeconds(1f)).Subscribe(_ => - { - state.Value = GameState.Success; - }).AddTo(this); break; case StageItem.Type.Item1: break; @@ -294,16 +295,13 @@ namespace MyGame.Scenes.MiniGame.Scripts scoreCount.Value = 0; resultManager.Reset(); gameCompositeDisposable.Clear(); - state.SkipLatestValueOnSubscribe().Subscribe(x => - { - if (x == GameState.Success) + state.SkipLatestValueOnSubscribe() + .First(x => x == GameState.Success) + .SelectMany(Observable.Timer(TimeSpan.FromSeconds(resultWaitTime))) + .Subscribe(x => { - this.CallWaitForSeconds(1f, () => - { - resultManager.ShowResult(scoreCount.Value, placeList, stageData); - }); - } - }).AddTo(gameCompositeDisposable); + resultManager.ShowResult(scoreCount.Value, placeList, stageData); + }).AddTo(gameCompositeDisposable); resultManager.OnRetry.ThrottleFirst(TimeSpan.FromSeconds(.2f)).Subscribe(_ => { diff --git a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs index 3e9a0bac..aa3b17cb 100644 --- a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs +++ b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs @@ -14,6 +14,7 @@ namespace MyGame.Scenes.MiniGame.Scripts [SerializeField] private float hitJumpTime = 1f; [SerializeField] private float hitTime = 1.5f; [SerializeField] private float hitWaitTime = 1f; + [SerializeField] private float hitStopTime = 1f; [SerializeField] private AnimationCurve jumpAnimationCurve; [SerializeField] private AnimationCurve hitAnimationCurve; [SerializeField] private float flyingFallSpeed = 1f; @@ -37,6 +38,7 @@ namespace MyGame.Scenes.MiniGame.Scripts private bool isHole; private bool isWall; private bool isResult; + private bool isHitStop; private float currentFallSpeed; private float currentSpeedMultiply; public bool IsHit => isHit; @@ -46,12 +48,16 @@ namespace MyGame.Scenes.MiniGame.Scripts private readonly ReactiveProperty count = new ReactiveProperty(); public IObservable OnHitItem => itemHitCollider.OnTriggerEnter2DAsObservable().TakeUntilDestroy(this); public IObservable OnHitObstacle => obstacleHitCollider.OnTriggerEnter2DAsObservable().TakeUntilDestroy(this); - + + private readonly Subject endHitSubject = new(); + public IObservable OnEndHit => endHitSubject; + private void Start() { count.AddTo(this); jumpCompositeDisposable.AddTo(this); hitCompositeDisposable.AddTo(this); + endHitSubject.AddTo(this); animator = GetComponent(); basePos = transform.localPosition; @@ -74,6 +80,7 @@ namespace MyGame.Scenes.MiniGame.Scripts isHole = false; isWall = false; isResult = false; + isHitStop = false; currentSpeedMultiply = 1f; } @@ -88,7 +95,7 @@ namespace MyGame.Scenes.MiniGame.Scripts public void Move() { - if (isHitStay || isWall) + if (isHitStay || isWall || isHitStop) { return; } @@ -192,18 +199,31 @@ namespace MyGame.Scenes.MiniGame.Scripts } Instantiate(hitEffectPrefab, hitPos, Quaternion.identity, transform.parent); - animator?.Play("Brother_pink_FallDown", 0, 0f); isHit = true; + isHitStop = true; hitCompositeDisposable.Clear(); jumpCompositeDisposable.Clear(); + + animator?.Play("Brother_pink_FallDown", 0, 0f); + animator.speed = 0f; + + var hitStopTimer = Observable.Timer(TimeSpan.FromSeconds(hitStopTime)).Share(); + hitStopTimer.Subscribe(_ => + { + isHitStop = false; + animator.speed = currentSpeedMultiply; + }).AddTo(hitCompositeDisposable); + var cachePosY = transform.localPosition.y; var diffHeight = cachePosY - basePos.y; var groundPos = isHole ? cachePosY : basePos.y; - var hitJumpCoroutine = MonoBehaviourExtensions.DoCallLerp(diffHeight <= 0f ? 0f : hitJumpTime, t => + var hitJumpCoroutine = MonoBehaviourExtensions.DoCallLerp(diffHeight <= 0f ? 0f : hitJumpTime / currentSpeedMultiply, t => { transform.SetLocalPositionY(cachePosY + hitAnimationCurve.Evaluate(t)); }); - Observable.FromCoroutine(_ => hitJumpCoroutine).Subscribe(_ => + + // HitStop後、Hit跳ね返りアニメーション + hitStopTimer.SelectMany(hitJumpCoroutine).Subscribe(_ => { // 落下時間不定によりアニメ再生停止 animator.speed = 0f; @@ -217,12 +237,12 @@ namespace MyGame.Scenes.MiniGame.Scripts currentFallSpeed = 0f; isJump = false; isFall = false; - Observable.Timer(TimeSpan.FromSeconds(hitTime)).Subscribe(_ => { }, () => + Observable.Timer(TimeSpan.FromSeconds(hitTime / currentSpeedMultiply)).Subscribe(_ => { }, () => { isHitStay = true; Observable.Timer(TimeSpan.FromSeconds(hitWaitTime)).Subscribe(_ => { }, () => { - // 入れ子対策するならコルーチンにして工程ごとに分けてSelectManyするのがよい。 + endHitSubject.OnNext(Unit.Default); isHit = false; isHitStay = false; if (isResult) diff --git a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/StageManager.cs b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/StageManager.cs index e3f00863..85bbb20e 100644 --- a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/StageManager.cs +++ b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/StageManager.cs @@ -29,15 +29,6 @@ namespace MyGame.Scenes.MiniGame.Scripts fenceSubject.AddTo(this); difficulty.AddTo(this); } - - /* - * ステージ自動生成 - * タイマーによってCurrentDifficulteyが切り替わると生成コース変更 - * 生成単位を3コース先など指定可能(分けて生成したほうが負荷が低そう?調査次第) - * Difficultyでゲームスピード切り替え - * ゲームスピード切り替えではdeltaTimeを倍にする - * deltaTime以外の影響はプレイヤーのAnimatorのSpeed(倍速と連動) - */ public void SetBeginStages(Transform[] newStages) {