diff --git a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs index f98b85e5..36414781 100644 --- a/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs +++ b/popcorn/Assets/MyGame/Scenes/MiniGame/Scripts/Player.cs @@ -15,6 +15,7 @@ namespace MyGame.Scenes.MiniGame.Scripts [SerializeField] private AnimationCurve hitAnimationCurve; [SerializeField] private float flyingFallSpeed = 1f; [SerializeField] private float fallAcceleration = 9.8f; + [SerializeField] private float fallLimit = -6f; [SerializeField] private GameObject itemHitCollider; [SerializeField] private GameObject obstacleHitCollider; [SerializeField] private GameObject level1; @@ -28,18 +29,15 @@ namespace MyGame.Scenes.MiniGame.Scripts private bool isJump; private bool isFall; private bool isButtonHold; - private bool isFlying; - private bool isResult; private bool isHit; + private bool isHitStay; private bool isHole; private bool isWall; + private bool isResult; private float currentFallSpeed; public bool IsHit => isHit; - private readonly BoolReactiveProperty isHitStay = new BoolReactiveProperty(); + private readonly CompositeDisposable jumpCompositeDisposable = new CompositeDisposable(); private readonly CompositeDisposable hitCompositeDisposable = new CompositeDisposable(); - private IDisposable jumpHoldDisposable; - private Coroutine jumpCoroutine; - private Coroutine jumpFallCoroutine; private Vector3 basePos; private readonly ReactiveProperty count = new ReactiveProperty(); public IObservable OnHitItem => itemHitCollider.OnTriggerEnter2DAsObservable().TakeUntilDestroy(this); @@ -47,8 +45,8 @@ namespace MyGame.Scenes.MiniGame.Scripts private void Start() { - isHitStay.AddTo(this); count.AddTo(this); + jumpCompositeDisposable.AddTo(this); hitCompositeDisposable.AddTo(this); animator = GetComponent(); basePos = transform.localPosition; @@ -67,9 +65,8 @@ namespace MyGame.Scenes.MiniGame.Scripts ResetCount(); isJump = false; isFall = false; - isFlying = false; isHit = false; - isHitStay.Value = false; + isHitStay = false; isHole = false; isWall = false; isResult = false; @@ -86,12 +83,12 @@ namespace MyGame.Scenes.MiniGame.Scripts public void Move() { - if (isHitStay.Value || isWall) + if (isHitStay || isWall) { return; } transform.AddPositionX(speed * Time.deltaTime); - if (isJump || isHit || isHole) + if (isJump || isHit || isFall) { return; } @@ -100,88 +97,84 @@ namespace MyGame.Scenes.MiniGame.Scripts public void Jump() { - if (isJump || isHit || isHole) + if (isJump || isHit || isFall) { return; } animator?.Play("Brother_pink_jump", 0, 0); + jumpCompositeDisposable.Clear(); isJump = true; isFall = false; var lastFrame = jumpAnimationCurve[jumpAnimationCurve.length - 1]; // 最高点までのジャンプ - jumpCoroutine = this.CallLerp(lastFrame.time, t => + var jumpCoroutine = MonoBehaviourExtensions.DoCallLerp(lastFrame.time, t => { transform.SetLocalPositionY(basePos.y + jumpAnimationCurve.Evaluate(t * lastFrame.time)); }, () => { // 最高点到達後、落下 + isJump = false; isFall = true; - jumpFallCoroutine = this.CallLerp(lastFrame.time, t => - { - transform.SetLocalPositionY(basePos.y + jumpAnimationCurve.Evaluate(t * lastFrame.time + lastFrame.time)); - }, () => - { - isJump = false; - isFall = false; - if (isResult) - { - Result(); - } - }); }); + // 通常落下 + var jumpFallCoroutine = MonoBehaviourExtensions.DoCallLerp(lastFrame.time, t => + { + transform.SetLocalPositionY(basePos.y + jumpAnimationCurve.Evaluate((t + 1) * lastFrame.time)); + }, () => + { + isFall = false; + if (isResult) + { + Result(); + } + }); + Observable.FromCoroutine(_ => jumpCoroutine) + .SelectMany(_ => jumpFallCoroutine) + .Subscribe().AddTo(jumpCompositeDisposable); + // ボタンが押されたら滑空モード開始 + this.UpdateAsObservable() + .First(_ => isButtonHold && isFall) + .Subscribe(_ => Flying()).AddTo(jumpCompositeDisposable); } /// /// ジャンプ最高点到達後 isFall /// 滑空時はflyingFallSpeedで緩やかに落ちる。滑空後にボタン離すとfallSpeedで落ちる /// - /// - public void SetJumpHold(bool active) + private void Flying() { - if (isHit) - { - return; - } - - isButtonHold = active; - // 滑空モード開始 - if (isFall && active && !isFlying) - { - isFlying = true; - currentFallSpeed = 0f; - this.SafeStopCoroutine(jumpFallCoroutine); - jumpHoldDisposable?.Dispose(); - jumpHoldDisposable = this.UpdateAsObservable() - .TakeWhile(_ => transform.localPosition.y > basePos.y) - .Subscribe(_ => + currentFallSpeed = 0f; + jumpCompositeDisposable.Clear(); + this.UpdateAsObservable() + .TakeWhile(_ => transform.localPosition.y > basePos.y) + .Subscribe(_ => + { + // 滑空or落下切り替え + if (isButtonHold) { - // 滑空or落下切り替え - if (isButtonHold) - { - animator.Play("Brother_pink_Gliding"); - currentFallSpeed = -flyingFallSpeed; - } - else - { - Stay(); - currentFallSpeed -= fallAcceleration * Time.deltaTime; - } - - transform.AddLocalPositionY(currentFallSpeed * Time.deltaTime); - }, () => + animator.Play("Brother_pink_Gliding"); + currentFallSpeed = -flyingFallSpeed; + } + else { - currentFallSpeed = 0f; - isJump = false; - isFall = false; - isFlying = false; - if (isResult) - { - Result(); - } - }).AddTo(this); - } + Stay(); + currentFallSpeed -= fallAcceleration * Time.deltaTime; + } + + transform.AddLocalPositionY(currentFallSpeed * Time.deltaTime); + }, () => + { + currentFallSpeed = 0f; + isFall = false; + if (isResult) + { + Result(); + } + }).AddTo(jumpCompositeDisposable); } + + public void SetJumpHold(bool active) => isButtonHold = active; // こける public void Hit(Vector3 hitPos) @@ -194,26 +187,22 @@ namespace MyGame.Scenes.MiniGame.Scripts Instantiate(hitEffectPrefab, hitPos, Quaternion.identity, transform.parent); animator?.Play("Brother_pink_FallDown", 0, 0f); isHit = true; - hitCompositeDisposable?.Clear(); - - // ヒット以外動作停止 - this.SafeStopCoroutine(jumpCoroutine); - this.SafeStopCoroutine(jumpFallCoroutine); - jumpHoldDisposable?.Dispose(); - + hitCompositeDisposable.Clear(); + jumpCompositeDisposable.Clear(); var cachePosY = transform.localPosition.y; var diffHeight = cachePosY - basePos.y; var groundPos = isHole ? cachePosY : basePos.y; - jumpCoroutine = this.CallLerp(diffHeight <= 0f ? 0f : hitJumpTime, t => + var hitJumpCoroutine = MonoBehaviourExtensions.DoCallLerp(diffHeight <= 0f ? 0f : hitJumpTime, t => { transform.SetLocalPositionY(cachePosY + hitAnimationCurve.Evaluate(t)); - }, () => + }); + Observable.FromCoroutine(_ => hitJumpCoroutine).Subscribe(_ => { // 落下時間不定によりアニメ再生停止 animator.speed = 0f; currentFallSpeed = 0f; this.UpdateAsObservable() - .TakeWhile(_ => transform.localPosition.y > groundPos) + .TakeWhile(_ => transform.localPosition.y > basePos.y) .Subscribe(_ => { currentFallSpeed -= fallAcceleration * Time.deltaTime; @@ -227,14 +216,14 @@ namespace MyGame.Scenes.MiniGame.Scripts currentFallSpeed = 0f; isJump = false; isFall = false; - isFlying = false; Observable.Timer(TimeSpan.FromSeconds(hitTime)).Subscribe(_ => { }, () => { - isHitStay.Value = true; + isHitStay = true; Observable.Timer(TimeSpan.FromSeconds(hitWaitTime)).Subscribe(_ => { }, () => { + // 入れ子対策するならコルーチンにして工程ごとに分けてSelectManyするのがよい。 isHit = false; - isHitStay.Value = false; + isHitStay = false; if (isResult) { Result(); @@ -246,31 +235,35 @@ namespace MyGame.Scenes.MiniGame.Scripts }).AddTo(hitCompositeDisposable); }).AddTo(hitCompositeDisposable); }).AddTo(hitCompositeDisposable); - }); + }).AddTo(hitCompositeDisposable); } public void Hole() { // 落下開始 isHole = true; - - // animator?.Play("Brother_pink_main_stay"); + isFall = true; isJump = false; - isFall = false; - isFlying = false; isHit = false; - isHitStay.Value = false; - hitCompositeDisposable?.Clear(); - jumpHoldDisposable?.Dispose(); - jumpHoldDisposable = this.UpdateAsObservable() - // .TakeWhile(_ => transform.localPosition.y > basePos.y) + isHitStay = false; + + hitCompositeDisposable.Clear(); + jumpCompositeDisposable.Clear(); + this.UpdateAsObservable() + .TakeWhile(_ => transform.localPosition.y > fallLimit) .Subscribe(_ => { currentFallSpeed -= fallAcceleration * Time.deltaTime; transform.AddLocalPositionY(currentFallSpeed * Time.deltaTime); }, () => { - }).AddTo(this); + isFall = false; + currentFallSpeed = 0f; + if (isResult) + { + Result(); + } + }).AddTo(jumpCompositeDisposable); } public void Wall() @@ -280,13 +273,14 @@ namespace MyGame.Scenes.MiniGame.Scripts public void Result() { - if (isJump || isHit) + if (isJump || isHit || isFall) { isResult = true; return; } isResult = false; animator?.Play("Brother_pink_glad"); + animator.speed = 1f; } public void AddCount()