feat(combat): 弹反投射物伤害目标层改为显式配置

ProjectileConfigSO 新增 ReflectedTargetLayers:弹反后写入 HitBox.TargetLayers 的目标层显式配置;留空(Nothing)有明确缺省语义=自动翻转(PlayerHurtBox 位换 EnemyHurtBox 位、其余位保留)。Projectile/ParryableProjectile 两条弹反路径统一走 ApplyReflectedTargetLayers。现有 6 个投射物配置资产已显式配为 EnemyHurtBox。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-12 10:43:57 +08:00
parent 1866f323e4
commit 5922ef373d
9 changed files with 41 additions and 7 deletions

View File

@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: PROJ_Boomerang_Config
m_EditorClassIdentifier:
DamageSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2}
MaxHits: 1
Speed: 10
Lifetime: 6
LaunchAngleDeg: 0
@@ -21,3 +22,6 @@ MonoBehaviour:
PoolKey: PROJ_Boomerang
ParrySpeedMultiplier: 1.2
ParryDamageMultiplier: 2
ReflectedTargetLayers:
serializedVersion: 2
m_Bits: 134217728

View File

@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: PROJ_FeiZhi_Acid_Config
m_EditorClassIdentifier:
DamageSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2}
MaxHits: 1
Speed: 9
Lifetime: 4
LaunchAngleDeg: 45
@@ -21,3 +22,6 @@ MonoBehaviour:
PoolKey: PROJ_FeiZhi_Acid
ParrySpeedMultiplier: 1.2
ParryDamageMultiplier: 2
ReflectedTargetLayers:
serializedVersion: 2
m_Bits: 134217728

View File

@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: PROJ_TornadoLarge_Config
m_EditorClassIdentifier:
DamageSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2}
MaxHits: 1
Speed: 0
Lifetime: 5
LaunchAngleDeg: 0
@@ -21,3 +22,6 @@ MonoBehaviour:
PoolKey: PROJ_TornadoLarge
ParrySpeedMultiplier: 1.2
ParryDamageMultiplier: 2
ReflectedTargetLayers:
serializedVersion: 2
m_Bits: 134217728

View File

@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: PROJ_TornadoSmall_Config
m_EditorClassIdentifier:
DamageSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2}
MaxHits: 1
Speed: 7
Lifetime: 4
LaunchAngleDeg: 0
@@ -21,3 +22,6 @@ MonoBehaviour:
PoolKey: PROJ_TornadoSmall
ParrySpeedMultiplier: 1.2
ParryDamageMultiplier: 2
ReflectedTargetLayers:
serializedVersion: 2
m_Bits: 134217728

View File

@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: PROJ_WindStone_Config
m_EditorClassIdentifier:
DamageSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2}
MaxHits: 1
Speed: 6
Lifetime: 4
LaunchAngleDeg: -90
@@ -21,3 +22,6 @@ MonoBehaviour:
PoolKey: PROJ_WindStone
ParrySpeedMultiplier: 1.2
ParryDamageMultiplier: 2
ReflectedTargetLayers:
serializedVersion: 2
m_Bits: 134217728

View File

@@ -13,6 +13,7 @@ MonoBehaviour:
m_Name: PROJ_ZhiMu_Acid_Config
m_EditorClassIdentifier:
DamageSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2}
MaxHits: 1
Speed: 9
Lifetime: 4
LaunchAngleDeg: 45
@@ -21,3 +22,6 @@ MonoBehaviour:
PoolKey: PROJ_ZhiMu_Acid
ParrySpeedMultiplier: 1.2
ParryDamageMultiplier: 2
ReflectedTargetLayers:
serializedVersion: 2
m_Bits: 134217728

View File

@@ -36,10 +36,10 @@ namespace BaseGames.Combat
// 阵营随弹反翻转:切到 PlayerProjectile 层(否则碰撞矩阵
// EnemyProjectile↔EnemyHurtBox 不碰撞,反射后永远打不中敌人),
// 伤害目标层同步从玩家侧切到敌人侧
// 伤害目标层同步切换(优先取配置的 ReflectedTargetLayers
int playerProjLayer = LayerMask.NameToLayer("PlayerProjectile");
if (playerProjLayer >= 0) gameObject.layer = playerProjLayer;
RetargetToEnemyFaction();
ApplyReflectedTargetLayers();
if (_reflectSource != null)
DamageInfo = DamageInfo.From(_reflectSource);

View File

@@ -87,8 +87,8 @@ namespace BaseGames.Combat
// 重置 HitBox 命中记录,确保反射后可命中新目标
_hitBox.Deactivate();
_hitBox.Activate(_config?.DamageSource);
// 伤害目标随阵营翻转:玩家侧 → 敌人侧
RetargetToEnemyFaction();
// 伤害目标随阵营切换(优先取配置的显式目标层)
ApplyReflectedTargetLayers();
// 反射后重置命中预算,并跳过本次(弹反)命中的扣减,避免反射后立即被回收
_hitsRemaining = _maxHits;
@@ -96,11 +96,18 @@ namespace BaseGames.Combat
}
/// <summary>
/// 弹反换阵营后,把伤害目标从玩家侧切到敌人侧
/// (仅交换 PlayerHurtBox→EnemyHurtBox 位,保留可破坏物等其他目标层)。
/// 弹反换阵营后应用伤害目标层:
/// 优先使用 <see cref="ProjectileConfigSO.ReflectedTargetLayers"/> 的显式配置;
/// 未配置Nothing时自动翻转——仅交换 PlayerHurtBox→EnemyHurtBox 位,
/// 保留可破坏物等其他目标层。
/// </summary>
protected void RetargetToEnemyFaction()
protected void ApplyReflectedTargetLayers()
{
if (_config != null && _config.ReflectedTargetLayers.value != 0)
{
_hitBox.TargetLayers = _config.ReflectedTargetLayers;
return;
}
int playerHurt = LayerMask.NameToLayer("PlayerHurtBox");
int enemyHurt = LayerMask.NameToLayer("EnemyHurtBox");
if (playerHurt < 0 || enemyHurt < 0) return; // Layer 尚未创建,保留现有掩码

View File

@@ -26,5 +26,8 @@ namespace BaseGames.Combat
[Header("弹反")]
public float ParrySpeedMultiplier = 1.2f;
public float ParryDamageMultiplier = 2.0f;
[Tooltip("弹反后本投射物可造成伤害判定的 Layer显式配置写入 HitBox.TargetLayers。" +
"留空(Nothing) = 自动翻转:在原目标层基础上 PlayerHurtBox 位换为 EnemyHurtBox 位、其余位保留。")]
public LayerMask ReflectedTargetLayers;
}
}