- 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>
95 lines
3.1 KiB
C#
95 lines
3.1 KiB
C#
using UnityEngine;
|
||
|
||
namespace BaseGames.Player.States
|
||
{
|
||
/// <summary>
|
||
/// 抓墙状态(架构 05_PlayerModule §2)。
|
||
/// 进入条件:空中贴墙时,按下朝向墙壁的方向键(或蹬墙跳后的自动抓墙)。
|
||
/// 高度限制:若当前 Y > wallGrabY(首次抓该墙的高度),强制下滑且不可蹬墙跳;
|
||
/// 若当前 Y ≤ wallGrabY,静止悬挂,可蹬墙跳。
|
||
/// 释放条件:主动按下反方向键或落地。
|
||
/// </summary>
|
||
public class WallSlideState : PlayerStateBase
|
||
{
|
||
private bool _canWallJump;
|
||
private int _wallDir;
|
||
|
||
public WallSlideState(PlayerController owner) : base(owner) { }
|
||
|
||
public override void OnStateEnter()
|
||
{
|
||
if (AnimCfg?.WallSlide != null)
|
||
Anim?.Play(AnimCfg.WallSlide);
|
||
|
||
// 记录当前墙壁方向
|
||
_wallDir = Owner.WallDetector != null ? Owner.WallDetector.WallDirection : -Owner.FacingDirection;
|
||
if (_wallDir == 0) _wallDir = -Owner.FacingDirection;
|
||
|
||
// 记录首次抓墙高度(不同墙壁才重置)
|
||
Owner.RecordWallGrab(_wallDir, Owner.transform.position.y);
|
||
|
||
// 消耗蹬墙跳后的自动抓墙标记
|
||
Owner.SetPostWallJump(false);
|
||
|
||
Input.JumpStartedEvent += OnJumpPressed;
|
||
}
|
||
|
||
public override void OnStateExit()
|
||
{
|
||
Input.JumpStartedEvent -= OnJumpPressed;
|
||
}
|
||
|
||
public override void OnStateUpdate()
|
||
{
|
||
// 离开墙壁 → 下落
|
||
if (Owner.WallDetector == null || !Owner.WallDetector.IsTouchingWall)
|
||
{
|
||
Owner.TransitionTo(Owner.GetState<FallState>());
|
||
return;
|
||
}
|
||
|
||
// 着地 → 闲置
|
||
if (Move.IsGrounded)
|
||
{
|
||
Owner.TransitionTo(Owner.GetState<IdleState>());
|
||
return;
|
||
}
|
||
|
||
// 主动按下反方向键 → 松开墙壁下落
|
||
float moveX = Input.MoveInput.x;
|
||
if (Mathf.Abs(moveX) > 0.01f && (int)Mathf.Sign(moveX) == -_wallDir)
|
||
{
|
||
Owner.TransitionTo(Owner.GetState<FallState>());
|
||
return;
|
||
}
|
||
}
|
||
|
||
public override void OnStateFixedUpdate()
|
||
{
|
||
// 每帧重新判断是否允许蹬墙跳(随下滑高度动态变化)
|
||
float currentY = Owner.transform.position.y;
|
||
_canWallJump = currentY <= Owner.WallGrabY + Cfg.WallGrabMaxHeightGain;
|
||
|
||
if (_canWallJump)
|
||
{
|
||
// 高度合法:静止悬挂(冻结垂直速度)
|
||
var vel = Move.Rb.velocity;
|
||
if (vel.y < 0f)
|
||
Move.Rb.velocity = new Vector2(vel.x, 0f);
|
||
}
|
||
else
|
||
{
|
||
// 高度超限:强制下滑
|
||
Move?.ApplyWallSlide();
|
||
}
|
||
}
|
||
|
||
private void OnJumpPressed()
|
||
{
|
||
// 仅高度合法时才允许蹬墙跳
|
||
if (_canWallJump)
|
||
Owner.TransitionTo(Owner.GetState<WallJumpState>());
|
||
}
|
||
}
|
||
}
|