Files
zeling_v2/Assets/_Game/Scripts/Player/PlayerCombat.cs
Joywayer 09bdda970a feat(feedback): 命中/受击反馈支持固定位置与击中位置两种生成模式
DamageInfo 新增运行时字段 HitPoint:HitBox 结算时写入精确接触点
(ClosestPoint),HurtBox.ReceiveDamage 以解析后命中点兜底盖戳,
陷阱/环境等直调路径同样可用。IFeedbackPlayer.PlayHit/PlayTakeHit
增加命中点参数,全链路(武器实例→PlayerCombat→HurtState→
EnemyFeedback)透传。各 Feedback 组件命中/受击槽位新增
FeedbackPositionMode(Fixed=反馈链编排的固定位置 /
HitPoint=传入命中点,启用位置选项的模块在该点生成),由编排
反馈链的开发者在 Inspector 按表现选择;武器命中默认 HitPoint
(火花贴点),角色级默认 Fixed(震屏/振动与位置无关)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 11:48:37 +08:00

105 lines
4.3 KiB
C#

using UnityEngine;
using BaseGames.Combat;
using BaseGames.Feedback;
namespace BaseGames.Player
{
/// <summary>
/// 玩家战斗组件。
/// HitBox 随装备武器动态实例化到 [WeaponSocket] 子节点,通过 WeaponManager.ActiveHitBoxInstance 访问。
/// </summary>
public class PlayerCombat : MonoBehaviour
{
[SerializeField] private WeaponManager _weaponManager;
private PlayerStats _stats;
private PlayerMovement _movement;
private WeaponHitBoxInstance _currentHitBoxInstance;
private IFeedbackPlayer _feedback;
/// <summary>下劈 HitBox 命中确认事件(供 DownAttackState 订阅 pogo 弹跳逻辑)。</summary>
public event System.Action<DamageInfo> OnDownHitConfirmed;
private void Awake()
{
_stats = GetComponentInParent<PlayerStats>();
_movement = GetComponentInParent<PlayerMovement>();
_feedback = GetComponentInParent<IFeedbackPlayer>()
?? GetComponentInChildren<IFeedbackPlayer>()
?? NullFeedbackPlayer.Instance;
}
private void OnEnable()
{
if (_weaponManager != null)
_weaponManager.OnWeaponChanged += HandleWeaponChanged;
}
private void OnDisable()
{
if (_weaponManager != null)
_weaponManager.OnWeaponChanged -= HandleWeaponChanged;
UnsubscribeHitEvents();
}
private void HandleWeaponChanged(WeaponSO _)
{
UnsubscribeHitEvents();
_currentHitBoxInstance = _weaponManager.ActiveHitBoxInstance;
if (_currentHitBoxInstance != null)
{
_currentHitBoxInstance.OnDownHitConfirmed += HandleDownHitConfirmed;
_currentHitBoxInstance.OnHitConfirmed += OnHitConfirmed;
}
}
private void UnsubscribeHitEvents()
{
if (_currentHitBoxInstance == null) return;
_currentHitBoxInstance.OnDownHitConfirmed -= HandleDownHitConfirmed;
_currentHitBoxInstance.OnHitConfirmed -= OnHitConfirmed;
_currentHitBoxInstance = null;
}
private void HandleDownHitConfirmed(DamageInfo info) => OnDownHitConfirmed?.Invoke(info);
// ── HitBox 激活(由 State / AnimationEvent 调用)─────────────────────
/// <summary>
/// 激活 HitBox。
/// hitBoxId 非空时按 Id 精确激活 Prefab 中对应子节点;空 = 方向默认。
/// source 为 null 时回退到 WeaponSO.GetSourceByDir(dir)(方向第 0 段)。
/// </summary>
public void EnableWeaponHitBox(AttackDirection dir,
string hitBoxId = "", DamageSourceSO source = null)
{
source ??= _weaponManager?.ActiveWeapon?.GetSourceByDir(dir);
_weaponManager?.ActiveHitBoxInstance?.Activate(dir, source, transform, hitBoxId);
}
public void DisableWeaponHitBox(AttackDirection dir)
=> _weaponManager?.ActiveHitBoxInstance?.Deactivate(dir);
public void DisableAllWeaponHitBoxes()
=> _weaponManager?.ActiveHitBoxInstance?.DeactivateAll();
/// <summary>命中确认回调:增加灵力(由 HurtBox.ReceiveDamage 步骤 7 的 HitConfirmed 事件订阅)。</summary>
public void OnHitConfirmed(DamageInfo info)
{
int gain = _weaponManager?.ActiveWeapon?.soulPowerGain ?? 10;
_stats?.AddSoulPower(gain);
// 命中反馈:按伤害量决定力度档位
var weight = info.FinalDamage <= 5 ? HitWeight.Light
: info.FinalDamage <= 15 ? HitWeight.Medium
: HitWeight.Heavy;
_feedback.PlayHit(weight, info.HitPoint);
// 攻击命中反嵈:向攻击反方向施加微小后退冲量,增强打击感
if (_movement?.Rb != null && info.KnockbackDirection.x != 0f)
_movement.Rb.AddForce(
new UnityEngine.Vector2(UnityEngine.Mathf.Sign(-info.KnockbackDirection.x) * 2f, 0f),
UnityEngine.ForceMode2D.Impulse);
}
}
}