fix(combat): 弹反阵营感知——仅玩家弹反才翻转投射物阵营与目标层

新增 Projectile.ReflectBy(parrier):按弹反者根节点 Tag 区分阵营。玩家弹反走原 ReflectAsPlayerProjectile(切 PlayerProjectile 层+切换伤害目标层);敌人弹反敌人投射物时阵营层与目标层均保持不变(仍是敌方投射物、仍打玩家侧),仅反转方向并重置命中记录与预算。HurtBox 弹反分支改传弹反者 Transform;ParryableProjectile 手写弹反分支同步加阵营判断。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 10:49:23 +08:00
parent 5922ef373d
commit 862a1e5899
4 changed files with 36 additions and 9 deletions

View File

@@ -35,7 +35,7 @@ namespace BaseGames.Combat
[System.NonSerialized] public uint HitActivationId; [System.NonSerialized] public uint HitActivationId;
/// <summary> /// <summary>
/// 攻击来源投射物(仅当攻击方是 Projectile 时非 null /// 攻击来源投射物(仅当攻击方是 Projectile 时非 null
/// 用于弹反成功时调用 ReflectAsPlayerProjectile() 翻转阵营。 /// 用于弹反成功时调用 ReflectBy(parrier) 按弹反者阵营反射(玩家弹反才翻转阵营
/// [NonSerialized]MonoBehaviour 引用不参与 Unity 资产序列化。 /// [NonSerialized]MonoBehaviour 引用不参与 Unity 资产序列化。
/// </summary> /// </summary>
[System.NonSerialized] public Projectile SourceProjectile; [System.NonSerialized] public Projectile SourceProjectile;

View File

@@ -75,8 +75,9 @@ namespace BaseGames.Combat
{ {
if (_parrySystem.ConsumeParry()) if (_parrySystem.ConsumeParry())
{ {
// 若攻击来源是投射物,翻转其阵营 Layer 与飞行方向 // 若攻击来源是投射物,按弹反者阵营反射:
info.SourceProjectile?.ReflectAsPlayerProjectile(); // 玩家弹反翻转阵营 Layer 与伤害目标层;敌人弹反仅反转方向
info.SourceProjectile?.ReflectBy(transform);
return; return;
} }
} }

View File

@@ -34,12 +34,16 @@ namespace BaseGames.Combat
Direction = -Direction; Direction = -Direction;
_rb.velocity = Direction * _config.Speed * _config.ParrySpeedMultiplier; _rb.velocity = Direction * _config.Speed * _config.ParrySpeedMultiplier;
// 阵营随弹反翻转:切到 PlayerProjectile 层(否则碰撞矩阵 // 仅当弹反者是玩家时翻转阵营:切到 PlayerProjectile 层(否则碰撞矩阵
// EnemyProjectile↔EnemyHurtBox 不碰撞,反射后永远打不中敌人), // EnemyProjectile↔EnemyHurtBox 不碰撞,反射后永远打不中敌人),
// 伤害目标层同步切换(优先取配置的 ReflectedTargetLayers // 伤害目标层同步切换(优先取配置的 ReflectedTargetLayers
int playerProjLayer = LayerMask.NameToLayer("PlayerProjectile"); // 敌人弹反敌人投射物:阵营与目标层保持不变,仅上面已反转方向。
if (playerProjLayer >= 0) gameObject.layer = playerProjLayer; if (parrySystem.transform.root.CompareTag("Player"))
ApplyReflectedTargetLayers(); {
int playerProjLayer = LayerMask.NameToLayer("PlayerProjectile");
if (playerProjLayer >= 0) gameObject.layer = playerProjLayer;
ApplyReflectedTargetLayers();
}
if (_reflectSource != null) if (_reflectSource != null)
DamageInfo = DamageInfo.From(_reflectSource); DamageInfo = DamageInfo.From(_reflectSource);

View File

@@ -71,9 +71,31 @@ namespace BaseGames.Combat
} }
/// <summary> /// <summary>
/// 弹反:将投射物阵营从 EnemyProjectile 切换为 PlayerProjectile /// 阵营感知弹反入口:根据弹反者阵营决定反射行为
/// 玩家弹反 → 切 PlayerProjectile 层并切换伤害目标层(走 <see cref="ReflectAsPlayerProjectile"/>
/// 敌人弹反 → 阵营层与伤害目标层均保持不变(仍是敌方投射物、仍打玩家侧),仅反转方向并重置命中记录。
/// 由 HurtBox.ReceiveDamage() 在弹反成功后调用,传入弹反者 Transform。
/// </summary>
public virtual void ReflectBy(Transform parrier)
{
if (parrier != null && parrier.root.CompareTag("Player"))
{
ReflectAsPlayerProjectile();
return;
}
// ── 敌人弹反:不换阵营、不换目标层,仅反转飞行并重置判定 ──
Direction = -Direction;
_rb.velocity = -_rb.velocity;
_hitBox.Deactivate();
_hitBox.Activate(_config?.DamageSource);
_hitsRemaining = _maxHits;
_justReflected = true;
}
/// <summary>
/// 玩家弹反:将投射物阵营从 EnemyProjectile 切换为 PlayerProjectile。
/// 反转飞行方向,并重置 HitBox 命中记录使其能够命中新目标(敌人)。 /// 反转飞行方向,并重置 HitBox 命中记录使其能够命中新目标(敌人)。
/// 由 HurtBox.ReceiveDamage() 在弹反成功后调用。
/// </summary> /// </summary>
public virtual void ReflectAsPlayerProjectile() public virtual void ReflectAsPlayerProjectile()
{ {