Files
zeling_v2/Assets/_Game/Scripts/Player/States/FallState.cs
Joywayer 2a6a0b1861 feat: 实现抓墙高度记忆、背墙跳/对墙跳、蹬墙后自动抓墙
- PlayerController: 添加 wallGrabY/wallGrabDir/isPostWallJump 字段及 API
- WallSlideState: 高度限制(超限强制下滑不可蹬跳)+ 静止悬挂 + 反向键释放
- WallJumpState: 区分背墙跳(WallJumpAwayForce)/对墙跳(WallJumpBackForce)
  蹬墙后标记 PostWallJump 允许空中自动抓墙;恢复空中冲刺次数
- FallState/JumpState: 新增抓墙入口(朝向按键 OR PostWallJump 自动抓墙)
- PlayerMovement.WallJump: 增加 jumpAway 参数区分两种跳跃力
- IdleState/RunState: 落地时重置抓墙记录和蹬墙跳标记

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 12:12:24 +08:00

102 lines
4.4 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>
/// 下落状态。
/// - 郊狼跳CoyoteTimer > 0 时按跳跃 → 一段跳JumpState使用 JumpForce
/// - 二段跳CoyoteTimer 耗尽后按跳跃且 AirJumpsLeft > 0 → JumpState使用 DoubleJumpForce
/// - 空中冲刺HasAbility(AirDash) && HasAerialDash → AerialDashState。
/// - 增强下落重力FallGravityMult确保下落快于上升手感紧实。
/// </summary>
public class FallState : PlayerStateBase
{
public FallState(PlayerController owner) : base(owner) { }
public override void OnStateEnter()
{
if (AnimCfg?.Fall != null)
Anim.Play(AnimCfg.Fall);
}
public override void OnStateUpdate()
{
// ── 跳跃输入(郊狼跳 / 二段跳)────────────────────────────────────
if (Buffer.ConsumeJump())
{
if (Move.HasCoyoteTime)
{
// 郊狼跳:一段跳,使用 JumpForce
_owner.TransitionTo(_owner.GetState<JumpState>());
return;
}
if (Owner.AirJumpsLeft > 0)
{
// 二段跳:通过 SetDoubleJump 标记 JumpState 使用 DoubleJumpForce
Owner.UseAirJump();
Owner.GetState<JumpState>()?.SetDoubleJump(true);
_owner.TransitionTo(_owner.GetState<JumpState>());
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 (Move.IsGrounded)
{
Move.ZeroVelocity();
if (Mathf.Abs(Input.MoveInput.x) > 0.1f)
_owner.TransitionTo(_owner.GetState<RunState>());
else
_owner.TransitionTo(_owner.GetState<IdleState>());
return;
}
// ── 抓墙:贴墙 + 朝向墙壁按键,或蹬墙跳后的自动抓墙──────────────
var wd = Owner.WallDetector;
if (wd != null && wd.IsTouchingWall)
{
int wallDir = wd.WallDirection;
bool pressingTowardWall = Mathf.Abs(Input.MoveInput.x) > 0.01f
&& (int)Mathf.Sign(Input.MoveInput.x) == wallDir;
if (pressingTowardWall || Owner.IsPostWallJump)
{
_owner.TransitionTo(_owner.GetState<WallSlideState>());
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);
// 增强下落重力FallGravityMult下落比上升更快手感更紧实
if (Move.Rb.velocity.y < 0f)
{
float extraGrav = Physics2D.gravity.y * (Cfg.FallGravityMult - 1f) * Time.fixedDeltaTime;
Move.Rb.velocity = new Vector2(
Move.Rb.velocity.x,
Mathf.Max(Move.Rb.velocity.y + extraGrav, -Cfg.MaxFallSpeed));
}
}
}
}