HitStop実装

This commit is contained in:
kimura 2022-07-25 16:59:55 +09:00
parent 003bcf3b0f
commit 9af78cb3ac
3 changed files with 39 additions and 30 deletions

View File

@ -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<StageItem>(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(_ =>
{

View File

@ -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<int> count = new ReactiveProperty<int>();
public IObservable<Collider2D> OnHitItem => itemHitCollider.OnTriggerEnter2DAsObservable().TakeUntilDestroy(this);
public IObservable<Collider2D> OnHitObstacle => obstacleHitCollider.OnTriggerEnter2DAsObservable().TakeUntilDestroy(this);
private readonly Subject<Unit> endHitSubject = new();
public IObservable<Unit> OnEndHit => endHitSubject;
private void Start()
{
count.AddTo(this);
jumpCompositeDisposable.AddTo(this);
hitCompositeDisposable.AddTo(this);
endHitSubject.AddTo(this);
animator = GetComponent<Animator>();
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)

View File

@ -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)
{