fix(combat): HitBox 命中节奏统一 + 投射物穿透可配
HitBox 新增 HitMode Single/Interval:Interval 用 Enter/Exit 跟踪占用 + Update 轮询,对停留目标按间隔重判,不再依赖 OnTriggerEnter 单次语义。BodyContactDamage 改用 Interval 模式,修复停留在接触判定内、无敌结束后不再受伤的 bug;FlyingEnemy 接触伤害加按目标间隔节流。ProjectileConfigSO 新增 MaxHits 默认 1 即命中即消失,Projectile 按命中预算回收,修掉默认无限穿透;弹反守卫避免反射后立即回收。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,8 +4,12 @@ using UnityEngine;
|
||||
namespace BaseGames.Enemies
|
||||
{
|
||||
/// <summary>
|
||||
/// 接触伤害:组件启用时持续激活 HitBox,令敌人对接触到的目标定期造成伤害。
|
||||
/// 接触伤害:组件启用时把 HitBox 切到 Interval 模式并持续激活,
|
||||
/// 令敌人对停留在判定盒内的目标按固定间隔重复造成伤害。
|
||||
/// 适用于无攻击动画的简单障碍物、环境危险或测试场景。
|
||||
///
|
||||
/// 重复命中由 HitBox 的 Interval 节奏(Enter/Exit 跟踪占用 + Update 轮询)驱动,
|
||||
/// 不再依赖反复 Activate()——后者无法对已停留目标补发 OnTriggerEnter,会导致只命中一次。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(HitBox))]
|
||||
public class BodyContactDamage : MonoBehaviour
|
||||
@@ -13,20 +17,13 @@ namespace BaseGames.Enemies
|
||||
[SerializeField] private float _repeatInterval = 0.5f;
|
||||
|
||||
private HitBox _hitBox;
|
||||
private float _timer;
|
||||
|
||||
private void Awake() => _hitBox = GetComponent<HitBox>();
|
||||
private void OnEnable() { _hitBox?.Activate(); _timer = 0f; }
|
||||
private void OnDisable() => _hitBox?.Deactivate();
|
||||
|
||||
private void Update()
|
||||
private void OnEnable()
|
||||
{
|
||||
_timer += Time.deltaTime;
|
||||
if (_timer >= _repeatInterval)
|
||||
{
|
||||
_timer = 0f;
|
||||
_hitBox.Activate();
|
||||
}
|
||||
_hitBox?.SetIntervalMode(_repeatInterval);
|
||||
_hitBox?.Activate();
|
||||
}
|
||||
private void OnDisable() => _hitBox?.Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using BaseGames.Combat;
|
||||
|
||||
@@ -22,8 +23,12 @@ namespace BaseGames.Enemies
|
||||
|
||||
[Header("接触伤害")]
|
||||
[SerializeField] private DamageSourceSO _contactDamageSource;
|
||||
[Tooltip("对停留在体接触范围内的同一目标重复造成伤害的间隔(秒)。")]
|
||||
[SerializeField] private float _contactInterval = 0.5f;
|
||||
|
||||
private Rigidbody2D _rb;
|
||||
// 按目标节流:避免 OnTriggerStay2D 每个物理帧都造成伤害(与 HitBox.Interval 节奏一致)
|
||||
private readonly Dictionary<HurtBox, float> _contactTimers = new();
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
@@ -55,6 +60,12 @@ namespace BaseGames.Enemies
|
||||
var hurtBox = other.GetComponent<HurtBox>();
|
||||
if (hurtBox == null) return;
|
||||
|
||||
// 按目标间隔节流:停留接触时每 _contactInterval 秒最多结算一次,
|
||||
// 不再每个物理帧都调用 ReceiveDamage(命中是否生效仍由承伤方无敌帧决定)。
|
||||
float now = Time.time;
|
||||
if (_contactTimers.TryGetValue(hurtBox, out float last) && now - last < _contactInterval) return;
|
||||
_contactTimers[hurtBox] = now;
|
||||
|
||||
Vector2 knockDir = ((Vector2)other.bounds.center - _rb.position).normalized;
|
||||
var info = DamageInfo.From(
|
||||
_contactDamageSource,
|
||||
|
||||
Reference in New Issue
Block a user