Files
zeling_v2/Assets/_Game/Scripts/Combat/ParryableProjectile.cs
T
joywayerandClaude Opus 4.8 862a1e5899 fix(combat): 弹反阵营感知——仅玩家弹反才翻转投射物阵营与目标层
新增 Projectile.ReflectBy(parrier):按弹反者根节点 Tag 区分阵营。玩家弹反走原 ReflectAsPlayerProjectile(切 PlayerProjectile 层+切换伤害目标层);敌人弹反敌人投射物时阵营层与目标层均保持不变(仍是敌方投射物、仍打玩家侧),仅反转方向并重置命中记录与预算。HurtBox 弹反分支改传弹反者 Transform;ParryableProjectile 手写弹反分支同步加阵营判断。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:49:23 +08:00

72 lines
3.0 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)。
// 敌人弹反敌人投射物:阵营与目标层保持不变,仅上面已反转方向。
if (parrySystem.transform.root.CompareTag("Player"))
{
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;
}
}
}