Files
zeling_v2/Assets/_Game/Scripts/Player/States/JumpState.cs
2026-05-17 07:56:12 +08:00

90 lines
3.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
namespace BaseGames.Player.States
{
/// <summary>
/// 跳跃状态。
/// - 一段跳 / 郊狼跳OnStateEnter 时调用 Move.Jump()。
/// - 二段跳(二段跳能力解锁后可用):上升或下落途中再按跳跃且 AirJumpsLeft > 0
/// 调用 Move.DoubleJump(),重播跳跃动画,不离开本状态(保持速度截断逻辑)。
/// - 空中冲刺:上升途中按冲刺且 HasAbility(AirDash) → AerialDashState。
/// - 变高跳:松开跳跃键触发 JumpCancelledEvent → CutJump()(系数 = JumpCutMultiplier
/// - _isDoubleJump由 FallState 在转换前通过 SetDoubleJump(true) 预设,
/// 使 OnStateEnter 对二段跳调用 Move.DoubleJump() 而非 Move.Jump()。
/// </summary>
public class JumpState : PlayerStateBase
{
private bool _isDoubleJump;
public JumpState(PlayerController owner) : base(owner) { }
/// <summary>
/// 由 FallState 在转换到 JumpState 前调用,标记本次进入为二段跳,
/// 以便 OnStateEnter 使用 DoubleJumpForce 而非 JumpForce。
/// </summary>
public void SetDoubleJump(bool isDouble) => _isDoubleJump = isDouble;
public override void OnStateEnter()
{
if (AnimCfg?.Jump != null)
Anim.Play(AnimCfg.Jump);
if (_isDoubleJump)
Move.DoubleJump();
else
Move.Jump();
_isDoubleJump = false; // 消耗标记
Input.JumpCancelledEvent += OnJumpCancelled;
}
public override void OnStateUpdate()
{
// 上升结束时转为下落
if (Move.Rb.velocity.y <= 0f)
{
_owner.TransitionTo(_owner.GetState<FallState>());
return;
}
// 空中冲刺(优先于二段跳:冲刺可保存二段跳机会)
if (Buffer.ConsumeDash()
&& Stats != null && Stats.HasAbility(AbilityType.AirDash))
{
var aerialDash = Owner.GetState<AerialDashState>();
if (aerialDash != null && aerialDash.HasAerialDash)
{
_owner.TransitionTo(aerialDash);
return;
}
}
// 二段跳:上升阶段即可触发(上升途中任意时刻可二段跳)
if (Buffer.ConsumeJump() && Owner.AirJumpsLeft > 0)
{
Owner.UseAirJump();
Move.DoubleJump();
// 留在 JumpState速度截断JumpCancelledEvent和落地检测逻辑继续生效
if (AnimCfg?.Jump != null) Anim?.Play(AnimCfg.Jump);
return;
}
}
public override void OnStateFixedUpdate()
{
// 空中水平移动:有输入时立即覆盖至目标速度;无输入时施加空气阻力保留动量
if (Mathf.Abs(Input.MoveInput.x) > 0.01f)
Move.Move(Input.MoveInput.x * Cfg.RunSpeed);
else
Move.ApplyAirDrag(Cfg.AirDragFactor);
}
public override void OnStateExit()
{
Input.JumpCancelledEvent -= OnJumpCancelled;
}
private void OnJumpCancelled() => Move.CutJump();
}
}