From 8515dfa7ab75909f5aa5704b37ee370064bced39 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Fri, 12 Jun 2026 09:51:17 +0800 Subject: [PATCH] =?UTF-8?q?feat(combat):=20=E4=B8=8B=E5=8A=88=E5=BC=B9?= =?UTF-8?q?=E8=B7=B3=E5=AE=8C=E5=96=84=E2=80=94=E2=80=94=E5=8F=AF=E7=A0=B4?= =?UTF-8?q?=E5=9D=8F=E7=89=A9=E5=8F=AF=E5=BC=B9=E8=B7=B3+=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E5=BC=B9=E8=B7=B3=E5=8A=9B+=E4=B8=8B=E5=8A=88?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E7=A9=BA=E4=B8=AD=E6=93=8D=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HitBox 新增 OnBreakableHitConfirmed:命中 IBreakable 也发命中确认, 下劈打可破坏物同样弹跳;不走 OnHitConfirmed,灵力仍只来自敌人 - 新增 PogoBounceForce 配置(默认 15,略低于 JumpForce=18)+ PlayerMovement.PogoBounce(),弹跳高度独立可调、固定不可截断 - DownAttackState 增加 OnStateFixedUpdate:下劈期间保留完整空中 水平操控(含与 FallState 同款贴墙保护) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Player/PLY_PlayerMovementConfig.asset | 1 + Assets/_Game/Scripts/Combat/HitBox.cs | 10 ++++++++ Assets/_Game/Scripts/Player/PlayerMovement.cs | 11 +++++++++ .../Scripts/Player/PlayerMovementConfigSO.cs | 4 ++++ .../Scripts/Player/States/DownAttackState.cs | 23 +++++++++++++++++-- .../Scripts/Player/WeaponHitBoxInstance.cs | 18 +++++++++++++-- 6 files changed, 63 insertions(+), 4 deletions(-) diff --git a/Assets/_Game/Data/Player/PLY_PlayerMovementConfig.asset b/Assets/_Game/Data/Player/PLY_PlayerMovementConfig.asset index 6e157b6..240a78f 100644 --- a/Assets/_Game/Data/Player/PLY_PlayerMovementConfig.asset +++ b/Assets/_Game/Data/Player/PLY_PlayerMovementConfig.asset @@ -29,6 +29,7 @@ MonoBehaviour: DashCooldown: 0.4 DashInvincibilityDuration: 0.2 DashInvincibilityCooldown: 0.9 + PogoBounceForce: 15 DownDashSpeed: 22 DownDashDuration: 0.25 WallSlideSpeed: 3 diff --git a/Assets/_Game/Scripts/Combat/HitBox.cs b/Assets/_Game/Scripts/Combat/HitBox.cs index 54929f8..0500d88 100644 --- a/Assets/_Game/Scripts/Combat/HitBox.cs +++ b/Assets/_Game/Scripts/Combat/HitBox.cs @@ -77,6 +77,13 @@ namespace BaseGames.Combat /// 命中确认委托(PlayerCombat / EnemyCombat 订阅)。 public event System.Action OnHitConfirmed; + /// + /// 命中可破坏物(IBreakable)确认事件。 + /// 与 OnHitConfirmed 区分:不走 HurtBox 伤害流水线,不参与灵力获取; + /// 供下劈弹跳等"打到实体即生效"的逻辑订阅。 + /// + public event System.Action OnBreakableHitConfirmed; + // 宿主投射物缓存(Activate 时填入,DamageInfo.SourceProjectile 写入用) private Projectile _ownerProjectile; @@ -260,7 +267,10 @@ namespace BaseGames.Combat // ③ 命中 IBreakable(机关/障碍物) if (other.TryGetComponent(out var breakable)) + { breakable.TryInteract(info); + OnBreakableHitConfirmed?.Invoke(info); + } } // ── 当前激活期已命中目标集合(防止复合子 Collider 导致同帧多次命中)──────────── diff --git a/Assets/_Game/Scripts/Player/PlayerMovement.cs b/Assets/_Game/Scripts/Player/PlayerMovement.cs index 7400e17..8de7025 100644 --- a/Assets/_Game/Scripts/Player/PlayerMovement.cs +++ b/Assets/_Game/Scripts/Player/PlayerMovement.cs @@ -214,6 +214,17 @@ namespace BaseGames.Player _rb.velocity = new Vector2(_rb.velocity.x, _rb.velocity.y * _config.JumpCutMultiplier); } + /// + /// 下劈命中弹跳(DownAttackState 调用)。覆盖当前垂直速度为 PogoBounceForce; + /// 固定高度(JumpCancelledEvent 仅 JumpState 处理,弹跳不受变高跳截断影响)。 + /// + public void PogoBounce() + { + _rb.velocity = new Vector2(_rb.velocity.x, _config.PogoBounceForce); + _coyoteTimer = 0f; + _slopeSnapDisabled = true; + } + /// /// 二段跳。覆盖当前垂直速度为 DoubleJumpForce。 /// FallState / JumpState 在检测到 HasAbility(DoubleJump) && AirJumpsLeft > 0 时调用。 diff --git a/Assets/_Game/Scripts/Player/PlayerMovementConfigSO.cs b/Assets/_Game/Scripts/Player/PlayerMovementConfigSO.cs index 0917655..9485a6a 100644 --- a/Assets/_Game/Scripts/Player/PlayerMovementConfigSO.cs +++ b/Assets/_Game/Scripts/Player/PlayerMovementConfigSO.cs @@ -60,6 +60,10 @@ namespace BaseGames.Player [Tooltip("无敌的独立冷却(秒)。CD 内再次冲刺不会获得无敌帧,防止连冲变相持续无敌(推荐 0.9s)。")] public float DashInvincibilityCooldown = 0.9f; + [Header("下劈弹跳(Pogo)")] + [Tooltip("下劈命中后的向上弹跳初速度。推荐略低于 JumpForce(如 JumpForce=18 时取 15),\n弹跳略矮于满跳;固定高度,不受变高跳截断影响。")] + public float PogoBounceForce = 15f; + [Header("下冲刺")] [Tooltip("向下冲刺速度(单位/秒)。推荐 22,快速向下穿透空间。")] public float DownDashSpeed = 22f; diff --git a/Assets/_Game/Scripts/Player/States/DownAttackState.cs b/Assets/_Game/Scripts/Player/States/DownAttackState.cs index 3754a61..6d883f5 100644 --- a/Assets/_Game/Scripts/Player/States/DownAttackState.cs +++ b/Assets/_Game/Scripts/Player/States/DownAttackState.cs @@ -58,10 +58,10 @@ namespace BaseGames.Player.States { if (_hasHitEnemy) return; _hasHitEnemy = true; - // Pogo 弹跳:命中敌人后向上弹起,同时重置空中能力(等同落地效果) + // Pogo 弹跳:命中后向上弹起(独立弹跳力,略矮于满跳),同时重置空中能力(等同落地效果) Owner.ResetAirJumps(); Owner.GetState()?.ResetDashCharge(); - Move.Jump(); + Move.PogoBounce(); } public override void OnStateUpdate() @@ -73,6 +73,25 @@ namespace BaseGames.Player.States } } + public override void OnStateFixedUpdate() + { + // 下劈期间保留完整空中水平操控(与 FallState 同款贴墙保护,防止压墙摩擦/卡角) + if (Mathf.Abs(Input.MoveInput.x) > 0.01f) + { + int inputDir = Input.MoveInput.x > 0 ? 1 : -1; + var wd = Owner.WallDetector; + bool currentFrameWall = inputDir > 0 ? Move.IsWallRight : Move.IsWallLeft; + if (currentFrameWall + || (wd != null && (wd.IsTouchingWall && wd.WallDirection == inputDir + || wd.HasPartialContact(inputDir)))) + Move.ZeroHorizontalVelocity(); + else + Move.Move(Input.MoveInput.x * Cfg.RunSpeed); + } + else + Move.ZeroHorizontalVelocity(); + } + private void OnClipEnd() { if (_exited) return; diff --git a/Assets/_Game/Scripts/Player/WeaponHitBoxInstance.cs b/Assets/_Game/Scripts/Player/WeaponHitBoxInstance.cs index 0b55717..84404ca 100644 --- a/Assets/_Game/Scripts/Player/WeaponHitBoxInstance.cs +++ b/Assets/_Game/Scripts/Player/WeaponHitBoxInstance.cs @@ -31,7 +31,7 @@ namespace BaseGames.Player private AttackDirection _activeDir; private IFeedbackPlayer _feedback; - /// 下劈命中确认事件(供 DownAttackState Pogo 逻辑)。 + /// 下劈命中确认事件(供 DownAttackState Pogo 逻辑)。命中 HurtBox 或可破坏物均触发。 public event System.Action OnDownHitConfirmed; /// 任意 HitBox 命中确认事件(供 PlayerCombat 订阅通用命中反馈)。 @@ -41,7 +41,10 @@ namespace BaseGames.Player { _allHitBoxes = GetComponentsInChildren(true); foreach (var hb in _allHitBoxes) - hb.OnHitConfirmed += OnAnyHitConfirmed; + { + hb.OnHitConfirmed += OnAnyHitConfirmed; + hb.OnBreakableHitConfirmed += OnAnyBreakableHitConfirmed; + } _feedback = GetComponentInChildren() ?? NullFeedbackPlayer.Instance; } @@ -57,6 +60,17 @@ namespace BaseGames.Player OnDownHitConfirmed?.Invoke(info); } + /// + /// 命中可破坏物:播放轻量打击反馈;下劈方向时同样触发弹跳。 + /// 不转发 OnHitConfirmed(可破坏物不参与灵力获取)。 + /// + private void OnAnyBreakableHitConfirmed(DamageInfo info) + { + _feedback.PlayHit(HitWeight.Light); + if (_activeDir == AttackDirection.Down) + OnDownHitConfirmed?.Invoke(info); + } + // ── 公共 API ────────────────────────────────────────────────────────── ///