プレイヤー挙動改善

This commit is contained in:
kimura 2022-07-25 10:50:11 +09:00
parent fb843dc20d
commit fce9a5668f
1 changed files with 86 additions and 92 deletions

View File

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