ProjectileConfigSO 新增 ReflectedTargetLayers:弹反后写入 HitBox.TargetLayers 的目标层显式配置;留空(Nothing)有明确缺省语义=自动翻转(PlayerHurtBox 位换 EnemyHurtBox 位、其余位保留)。Projectile/ParryableProjectile 两条弹反路径统一走 ApplyReflectedTargetLayers。现有 6 个投射物配置资产已显式配为 EnemyHurtBox。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
2.8 KiB
C#
68 lines
2.8 KiB
C#
using UnityEngine;
|
||
using BaseGames.Parry;
|
||
|
||
namespace BaseGames.Combat
|
||
{
|
||
/// <summary>
|
||
/// 可被玩家弹反的抛射物。
|
||
/// 触发时优先检测弹反窗口;若成功弹反则反向飞行并可切换伤害源;
|
||
/// 否则走正常伤害流水线。
|
||
/// </summary>
|
||
public class ParryableProjectile : LinearProjectile
|
||
{
|
||
[SerializeField] private DamageSourceSO _reflectSource;
|
||
|
||
private bool _reflected;
|
||
|
||
protected override void OnInitialized()
|
||
{
|
||
// 禁用子 HitBox 的自动检测,改由本组件的 OnTriggerEnter2D 手动处理,
|
||
// 以便在命中前插入弹反判断。
|
||
_hitBox.Deactivate();
|
||
_rb.velocity = Direction * _config.Speed;
|
||
}
|
||
|
||
private void OnTriggerEnter2D(Collider2D other)
|
||
{
|
||
// ── 弹反判断 ────────────────────────────────────────────────
|
||
if (!_reflected)
|
||
{
|
||
var parrySystem = other.GetComponentInParent<ParrySystem>();
|
||
if (parrySystem != null && parrySystem.IsParrying && parrySystem.ConsumeParry())
|
||
{
|
||
_reflected = true;
|
||
Direction = -Direction;
|
||
_rb.velocity = Direction * _config.Speed * _config.ParrySpeedMultiplier;
|
||
|
||
// 阵营随弹反翻转:切到 PlayerProjectile 层(否则碰撞矩阵
|
||
// EnemyProjectile↔EnemyHurtBox 不碰撞,反射后永远打不中敌人),
|
||
// 伤害目标层同步切换(优先取配置的 ReflectedTargetLayers)。
|
||
int playerProjLayer = LayerMask.NameToLayer("PlayerProjectile");
|
||
if (playerProjLayer >= 0) gameObject.layer = playerProjLayer;
|
||
ApplyReflectedTargetLayers();
|
||
|
||
if (_reflectSource != null)
|
||
DamageInfo = DamageInfo.From(_reflectSource);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// ── 正常命中 ─────────────────────────────────────────────────
|
||
// 本类绕过 HitBox 自行判定,需自行套用其伤害目标层过滤
|
||
if ((_hitBox.TargetLayers.value & (1 << other.gameObject.layer)) == 0) return;
|
||
var hurtBox = other.GetComponent<HurtBox>();
|
||
if (hurtBox != null)
|
||
{
|
||
hurtBox.ReceiveDamage(DamageInfo);
|
||
ReturnToPool();
|
||
}
|
||
}
|
||
|
||
protected override void OnDisable()
|
||
{
|
||
base.OnDisable();
|
||
_reflected = false;
|
||
}
|
||
}
|
||
}
|