跳跃靠墙高度修复
This commit is contained in:
@@ -41,15 +41,32 @@ namespace BaseGames.Player.States
|
||||
|
||||
_isDoubleJump = false; // 消耗标记
|
||||
Input.JumpCancelledEvent += OnJumpCancelled;
|
||||
// 开启上升阶段贴墙 vy 保护:防止物理摩擦降低跳跃最高点
|
||||
Move.SetPreserveVyOnWallContact(true);
|
||||
}
|
||||
|
||||
public override void OnStateUpdate()
|
||||
{
|
||||
// 上升结束时转为下落
|
||||
// 上升结束时转为下落。
|
||||
// 例外:按住朝墙方向且射线已检测到墙时,物理摩擦可能将 vy 瞬间压到 ≤ 0,
|
||||
// 此时不触发 FallState,让后续抓墙检测在 vy 稳定后接管状态转换,
|
||||
// 防止因一帧摩擦导致跳跃高度降低并错误进入 FallState。
|
||||
if (Move.Rb.velocity.y <= 0f)
|
||||
{
|
||||
_owner.TransitionTo(_owner.GetState<FallState>());
|
||||
return;
|
||||
bool pressingTowardDetectedWall = false;
|
||||
if (Mathf.Abs(Input.MoveInput.x) > 0.01f)
|
||||
{
|
||||
int inputDir = Input.MoveInput.x > 0 ? 1 : -1;
|
||||
bool cwRay = inputDir > 0 ? Move.IsWallRight : Move.IsWallLeft;
|
||||
var wd0 = Owner.WallDetector;
|
||||
pressingTowardDetectedWall = cwRay
|
||||
|| (wd0 != null && wd0.IsTouchingWall && wd0.WallDirection == inputDir);
|
||||
}
|
||||
if (!pressingTowardDetectedWall)
|
||||
{
|
||||
_owner.TransitionTo(_owner.GetState<FallState>());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ── 下冲刺(下 + 冲刺 → 向下冲刺,优先于普通冲刺)──────────────────────
|
||||
@@ -98,8 +115,10 @@ namespace BaseGames.Player.States
|
||||
}
|
||||
|
||||
// ── 抓墙:贴墙 + 朝向墙壁按键,或蹬墙跳后的自动抓墙──────────────
|
||||
// 仅在上升结束后(vy ≤ 0)才进入抓墙状态;上升阶段阻止转换以保留顶点重力缩减,
|
||||
// 避免贴墙按方向键导致跳跃最大高度降低。
|
||||
var wd = Owner.WallDetector;
|
||||
if (wd != null && wd.IsTouchingWall && !Move.IsGrounded)
|
||||
if (wd != null && wd.IsTouchingWall && !Move.IsGrounded && !Move.IsRising)
|
||||
{
|
||||
int wallDir = wd.WallDirection;
|
||||
bool pressingTowardWall = Mathf.Abs(Input.MoveInput.x) > 0.01f
|
||||
@@ -130,11 +149,19 @@ namespace BaseGames.Player.States
|
||||
{
|
||||
int inputDir = Input.MoveInput.x > 0 ? 1 : -1;
|
||||
var wd = Owner.WallDetector;
|
||||
// PlayerWallDetector(order 0)在状态机(order -100)之后执行,
|
||||
// 其 IsTouchingWall / HasPartialContact 对状态机而言是上一帧的结果。
|
||||
// PlayerMovement.CheckWalls()(order -200)在状态机之前执行,
|
||||
// IsWallLeft / IsWallRight 是当帧最新结果,可提前一帧停止施力,
|
||||
// 防止角色以 RunSpeed 压入墙面后物理引擎的摩擦力降低上升速度。
|
||||
bool currentFrameWall = inputDir > 0 ? Move.IsWallRight : Move.IsWallLeft;
|
||||
if (wd != null && wd.IsTouchingWall && wd.WallDirection == inputDir)
|
||||
{
|
||||
// 按下朝墙方向键 + 在墙上(且未著地)→ 进入抓墙状态
|
||||
// 仅在上升结束后(vy ≤ 0)才进入抓墙状态;上升阶段只停止水平施力,
|
||||
// 保留顶点重力缩减逻辑,防止贴墙按键导致跳跃最大高度降低。
|
||||
var wss = Owner.GetState<WallSlideState>();
|
||||
if (wss != null && !Move.IsGrounded)
|
||||
if (wss != null && !Move.IsGrounded && !Move.IsRising)
|
||||
{
|
||||
wss.PrepareEnter(inputDir);
|
||||
Owner.TransitionTo(wss);
|
||||
@@ -142,10 +169,10 @@ namespace BaseGames.Player.States
|
||||
}
|
||||
Move.ZeroHorizontalVelocity();
|
||||
}
|
||||
else if (wd != null && wd.HasPartialContact(inputDir))
|
||||
else if (currentFrameWall || (wd != null && wd.HasPartialContact(inputDir)))
|
||||
{
|
||||
// 仅部分射线命中(如检测点高于矮墙顶部),停止施加朝墙方向的水平速度,
|
||||
// 防止角色边角被卡在墙顶而无法继续下落。
|
||||
// 当帧单射线已检测到墙(PlayerMovement -200 先于状态机 -100 执行),
|
||||
// 或上一帧部分射线命中——停止施力,防止以 RunSpeed 压入墙面产生摩擦力。
|
||||
Move.ZeroHorizontalVelocity();
|
||||
}
|
||||
else
|
||||
@@ -160,6 +187,7 @@ namespace BaseGames.Player.States
|
||||
// 顶点悬停可能已降低重力,离开本状态时必须恢复;
|
||||
// 否则进入 FallState/DashState 等后续状态时重力仍低于默认值。
|
||||
Move.SetGravityScale(Cfg.DefaultGravityScale);
|
||||
Move.SetPreserveVyOnWallContact(false);
|
||||
Input.JumpCancelledEvent -= OnJumpCancelled;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user