Files
zeling_v2/Assets/_Game/Scripts/Player/States/WallJumpState.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

87 lines
3.2 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>
/// 蹬墙跳状态(架构 05_PlayerModule §2
/// 从 WallSlideState 进入;根据输入方向区分背墙跳与对墙跳;
/// 蹬墙后标记 PostWallJump允许空中靠近墙壁时自动抓墙无需方向键
/// 输入锁结束后如贴墙则自动进入 WallSlideState否则上升结束后转为 FallState。
/// </summary>
public class WallJumpState : PlayerStateBase
{
private float _inputLockTimer;
private int _wallDir;
private bool _jumpAway; // true = 背墙跳false = 对墙跳
public WallJumpState(PlayerController owner) : base(owner) { }
public override void OnStateEnter()
{
// 记录墙壁方向
_wallDir = Owner.WallDetector != null ? Owner.WallDetector.WallDirection : 0;
if (_wallDir == 0) _wallDir = -Owner.FacingDirection;
// 根据输入方向判断跳跃类型:
// 无输入或背离墙壁方向 → 背墙跳
// 朝向墙壁方向 → 对墙跳
float moveX = Input.MoveInput.x;
bool pressingTowardWall = Mathf.Abs(moveX) > 0.01f
&& (int)Mathf.Sign(moveX) == _wallDir;
_jumpAway = !pressingTowardWall;
// 施加蹬墙跳速度
Move?.WallJump(_wallDir, _jumpAway);
// 锁定水平输入,防止立即覆盖跳跃速度
_inputLockTimer = Cfg.WallJumpInputLockDuration;
// 标记蹬墙跳后自动抓墙(在 FallState/WallJumpState 中消耗)
Owner.SetPostWallJump(true);
// 蹬墙成功后立即恢复空中冲刺次数
Owner.GetState<AerialDashState>()?.ResetAerialDashes();
if (AnimCfg?.Jump != null) Anim?.Play(AnimCfg.Jump);
Input.JumpCancelledEvent += OnJumpCancelled;
}
public override void OnStateExit()
{
Input.JumpCancelledEvent -= OnJumpCancelled;
}
public override void OnStateUpdate()
{
// 输入锁结束后检查是否贴墙:自动抓墙(优先于下落判断)
if (_inputLockTimer <= 0f)
{
var wd = Owner.WallDetector;
if (wd != null && wd.IsTouchingWall && !Move.IsGrounded)
{
Owner.TransitionTo(Owner.GetState<WallSlideState>());
return;
}
}
// 上升结束 → 下落isPostWallJump 标记保留FallState 中继续支持自动抓墙)
if (!Move.IsRising)
{
Owner.TransitionTo(Owner.GetState<FallState>());
return;
}
}
public override void OnStateFixedUpdate()
{
_inputLockTimer -= Time.fixedDeltaTime;
// 输入锁结束后允许水平控制
if (_inputLockTimer <= 0f && Mathf.Abs(Input.MoveInput.x) > 0.01f)
Move?.Move(Input.MoveInput.x * Cfg.RunSpeed);
}
private void OnJumpCancelled() => Move?.CutJump();
}
}