using UnityEngine; namespace BaseGames.Player.States { /// /// 抓墙状态(架构 05_PlayerModule §2)。 /// 进入条件:空中贴墙时,按下朝向墙壁的方向键(或蹬墙跳后的自动抓墙)。 /// 高度限制:若当前 Y > wallGrabY(首次抓该墙的高度),强制下滑且不可蹬墙跳; /// 若当前 Y ≤ wallGrabY,静止悬挂,可蹬墙跳。 /// 释放条件:主动按下反方向键或落地。 /// 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()); return; } // 着地 → 闲置 if (Move.IsGrounded) { Owner.TransitionTo(Owner.GetState()); return; } // 主动按下反方向键 → 松开墙壁下落 float moveX = Input.MoveInput.x; if (Mathf.Abs(moveX) > 0.01f && (int)Mathf.Sign(moveX) == -_wallDir) { Owner.TransitionTo(Owner.GetState()); 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()); } } }