Files
zeling_v2/Assets/_Game/Scripts/Player/WeaponHitBoxInstance.cs
Joywayer b7baf7ad6a Add WeaponFeedback component and AddressableManagerWindow meta file
- Implemented WeaponFeedback class for handling weapon-related feedbacks such as hit effects and attack sounds.
- Added meta file for AddressableManagerWindow to manage addressable assets.
- Included a new jump.data file for profiler data.
2026-05-22 22:03:32 +08:00

107 lines
4.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using BaseGames.Combat;
using BaseGames.Feedback;
namespace BaseGames.Player
{
/// <summary>
/// 武器 HitBox 实例。
/// 由 WeaponManager 在切换武器时实例化到角色的 [WeaponSocket] 子节点下。
///
/// Prefab 层级示例(每段连击独立一个子节点,在 Prefab 内可视化编辑 Collider2D
/// [WPN_SkyBlade_HitBox] ← WeaponHitBoxInstance
/// ├── [HitBox_Ground] Id="" ← 方向默认ComboStepConfig.hitBoxId 为空时使用)
/// ├── [HitBox_Ground_1] Id="g1" ← 第 1 段专属判定
/// ├── [HitBox_Ground_2] Id="g2" ← 第 2 段专属判定
/// ├── [HitBox_Up] Id="" ← 上劈默认
/// ├── [HitBox_Down] Id="" ← 下劈默认
/// └── [HitBox_Air] Id="" ← 空中默认
///
/// ComboStepConfig.hitBoxId 留空 → 用方向默认;填 Id → 精确激活对应子节点。
/// </summary>
public class WeaponHitBoxInstance : MonoBehaviour
{
[Header("方向默认 HitBoxhitBoxId 为空时使用)")]
[SerializeField] private HitBox _hitBoxGround;
[SerializeField] private HitBox _hitBoxUp;
[SerializeField] private HitBox _hitBoxDown;
[SerializeField] private HitBox _hitBoxAir;
private HitBox[] _allHitBoxes;
private AttackDirection _activeDir;
private IFeedbackPlayer _feedback;
/// <summary>下劈命中确认事件(供 DownAttackState Pogo 逻辑)。</summary>
public event System.Action<DamageInfo> OnDownHitConfirmed;
/// <summary>任意 HitBox 命中确认事件(供 PlayerCombat 订阅通用命中反馈)。</summary>
public event System.Action<DamageInfo> OnHitConfirmed;
private void Awake()
{
_allHitBoxes = GetComponentsInChildren<HitBox>(true);
foreach (var hb in _allHitBoxes)
hb.OnHitConfirmed += OnAnyHitConfirmed;
_feedback = GetComponentInChildren<IFeedbackPlayer>() ?? NullFeedbackPlayer.Instance;
}
private void OnAnyHitConfirmed(DamageInfo info)
{
var weight = info.FinalDamage <= 5 ? HitWeight.Light
: info.FinalDamage <= 15 ? HitWeight.Medium
: HitWeight.Heavy;
_feedback.PlayHit(weight);
OnHitConfirmed?.Invoke(info);
if (_activeDir == AttackDirection.Down)
OnDownHitConfirmed?.Invoke(info);
}
// ── 公共 API ──────────────────────────────────────────────────────────
/// <summary>
/// 激活 HitBox。
/// hitBoxId 非空时按 Id 精确查找 Prefab 子节点;空 = 使用该方向的默认 HitBox。
/// </summary>
public void Activate(AttackDirection dir, DamageSourceSO source, Transform attacker,
string hitBoxId = "")
{
_activeDir = dir;
_feedback.PlayAttackWhoosh();
var hitBox = string.IsNullOrEmpty(hitBoxId)
? GetHitBox(dir)
: (GetHitBoxById(hitBoxId) ?? GetHitBox(dir));
hitBox?.Activate(source, attacker);
}
/// <summary>停用指定方向的默认 HitBox。</summary>
public void Deactivate(AttackDirection dir) => GetHitBox(dir)?.Deactivate();
/// <summary>停用 Prefab 中所有 HitBox。</summary>
public void DeactivateAll()
{
if (_allHitBoxes == null) return;
foreach (var hb in _allHitBoxes) hb.Deactivate();
}
/// <summary>按 HitBox.Id 查找子节点(未找到返回 null。</summary>
public HitBox GetHitBoxById(string id)
{
if (_allHitBoxes == null || string.IsNullOrEmpty(id)) return null;
foreach (var hb in _allHitBoxes)
if (hb.Id == id) return hb;
return null;
}
/// <summary>按攻击方向返回默认 HitBox。</summary>
public HitBox GetHitBox(AttackDirection dir) => dir switch
{
AttackDirection.Ground => _hitBoxGround,
AttackDirection.Up => _hitBoxUp,
AttackDirection.Down => _hitBoxDown,
AttackDirection.Air => _hitBoxAir,
_ => null,
};
}
}