角色能力,存档

This commit is contained in:
2026-05-19 11:50:21 +08:00
parent d25f237e76
commit 2dcb7a961a
136 changed files with 36035 additions and 27551 deletions

View File

@@ -3,16 +3,58 @@ using UnityEngine;
namespace BaseGames.Player.States
{
/// <summary>
/// 壁滑状态(架构 05_PlayerModule §2
/// 需有 PlayerWallDetector.IsTouchingWall == true 才能进入;
/// 限制下落速度为 WallSlideSpeed按跳跃则切换到 WallJumpState
/// 抓墙状态(自定义设计,架构 05_PlayerModule §2
///
/// 触发条件:空中贴墙时玩家按下朝向墙壁的方向键(由 FallState/JumpState 检测并调用 PrepareEnter
/// 维持条件:进入后无需持续按键;主动按下反方向键或落地时解除。
///
/// 高度记忆机制(防止单面墙反复爬升):
/// - 首次抓墙(或切换到另一侧墙壁)时记录 _wallGrabY。
/// - 若当前 Y > _wallGrabY + 容差 → 受限模式:持续下滑,不可蹬墙跳。
/// - 若当前 Y ≤ _wallGrabY + 容差 → 正常模式:静止悬挂,可触发蹬墙跳。
/// - 重置时机:① 落地时(由 IdleState/RunState 调用 ResetWallGrab
/// ② 切换到另一侧墙壁时OnStateEnter 内自动判断)。
/// </summary>
public class WallSlideState : PlayerStateBase
{
// ── 运行时状态 ────────────────────────────────────────────────────────
/// <summary>首次抓住该侧墙壁时记录的 Y 坐标。</summary>
private float _wallGrabY = float.MinValue;
/// <summary>上次记录 wallGrabY 时的墙壁方向(+1 右墙 / -1 左墙)。</summary>
private int _lastGrabDir = 0;
/// <summary>本次进入时确认的墙壁方向(由 PrepareEnter 设置)。</summary>
private int _wallDir = 0;
/// <summary>当前是否处于正常模式可蹬墙跳。受限模式isRestricted时不可跳。</summary>
private bool _canJump = false;
public WallSlideState(PlayerController owner) : base(owner) { }
/// <summary>
/// 由 FallState / JumpState 在调用 TransitionTo 之前调用,传入已确认的墙壁方向。
/// </summary>
public void PrepareEnter(int wallDir) => _wallDir = wallDir;
/// <summary>
/// 落地时由 IdleState / RunState 调用,重置高度记忆,允许下次抓同侧墙时重新计算。
/// </summary>
public void ResetWallGrab()
{
_wallGrabY = float.MinValue;
_lastGrabDir = 0;
}
public override void OnStateEnter()
{
// 若切换到另一侧墙壁,重置高度记录(视为全新的墙壁)
if (_wallDir != _lastGrabDir)
{
_wallGrabY = Owner.transform.position.y;
_lastGrabDir = _wallDir;
}
// 计算当前是否处于正常模式
UpdateCanJump();
if (AnimCfg?.WallSlide != null)
Anim?.Play(AnimCfg.WallSlide);
@@ -26,8 +68,10 @@ namespace BaseGames.Player.States
public override void OnStateUpdate()
{
var wd = Owner.WallDetector;
// 离开墙壁 → 下落
if (Owner.WallDetector == null || !Owner.WallDetector.IsTouchingWall)
if (wd == null || !wd.IsTouchingWall)
{
Owner.TransitionTo(Owner.GetState<FallState>());
return;
@@ -39,17 +83,52 @@ namespace BaseGames.Player.States
Owner.TransitionTo(Owner.GetState<IdleState>());
return;
}
// 主动按反方向键 → 脱离(松墙下落)
float mx = Input.MoveInput.x;
if (Mathf.Abs(mx) > 0.1f)
{
int inputDir = mx > 0f ? 1 : -1;
if (inputDir != _wallDir)
{
Owner.TransitionTo(Owner.GetState<FallState>());
return;
}
}
// 每帧刷新正常/受限状态
UpdateCanJump();
}
public override void OnStateFixedUpdate()
{
// 限制下落速度(壁滑缓慢下落)
Move?.ApplyWallSlide();
if (_canJump)
// 正常模式:静止悬挂,阻止向下速度
Move?.ZeroVerticalVelocity();
else
// 受限模式:持续下滑
Move?.ApplyWallSlide();
}
// ── 内部 ──────────────────────────────────────────────────────────────
private void UpdateCanJump()
{
float tolerance = Cfg?.WallGrabHeightTolerance ?? 0.05f;
_canJump = Owner.transform.position.y <= _wallGrabY + tolerance;
}
private void OnJumpPressed()
{
Owner.TransitionTo(Owner.GetState<WallJumpState>());
// 受限模式禁止蹬墙跳
if (!_canJump) return;
var wjs = Owner.GetState<WallJumpState>();
if (wjs == null) return;
wjs.PrepareEnter(_wallDir, Input.MoveInput.x);
Owner.TransitionTo(wjs);
}
}
}