完整启动流程

This commit is contained in:
2026-05-19 23:20:44 +08:00
parent d0a1112737
commit 5fd981f5b9
22 changed files with 1938 additions and 14 deletions

View File

@@ -27,6 +27,12 @@ namespace BaseGames.Combat
public BreakLevel Break;
public string SourceId;
public string SkillId;
/// <summary>
/// 攻击来源投射物(仅当攻击方是 Projectile 时非 null
/// 用于弹反成功时调用 ReflectAsPlayerProjectile() 翻转阵营。
/// [NonSerialized]MonoBehaviour 引用不参与 Unity 资产序列化。
/// </summary>
[System.NonSerialized] public Projectile SourceProjectile;
// ── Builder ──────────────────────────────────────────────────────────
/// <summary>
@@ -48,6 +54,7 @@ namespace BaseGames.Combat
private BreakLevel _break;
private Vector2 _sourcePosition;
private int _sourceLayer;
private Projectile _sourceProjectile;
public Builder() { }
@@ -65,6 +72,7 @@ namespace BaseGames.Combat
public Builder SetBreak(BreakLevel v) { _break = v; return this; }
public Builder SetSourcePos(Vector2 v) { _sourcePosition = v; return this; }
public Builder SetLayer(int v) { _sourceLayer = v; return this; }
public Builder SetProjectile(Projectile v) { _sourceProjectile = v; return this; }
public DamageInfo Build() => new DamageInfo
{
@@ -83,6 +91,7 @@ namespace BaseGames.Combat
Break = _break,
SourcePosition = _sourcePosition,
SourceLayer = _sourceLayer,
SourceProjectile = _sourceProjectile,
};
}
@@ -95,7 +104,8 @@ namespace BaseGames.Combat
DamageSourceSO so,
Vector2 knockbackDir = default,
Vector2 sourcePos = default,
int sourceLayer = 0)
int sourceLayer = 0,
Projectile sourceProjectile = null)
{
int baseAmt = Mathf.RoundToInt(so.BaseDamage * so.DamageMultiplier);
return new DamageInfo
@@ -115,6 +125,7 @@ namespace BaseGames.Combat
KnockbackForce = so.KnockbackForce,
SourcePosition = sourcePos,
SourceLayer = sourceLayer,
SourceProjectile = sourceProjectile,
};
}
}

View File

@@ -49,6 +49,9 @@ namespace BaseGames.Combat
/// <summary>命中确认委托PlayerCombat / EnemyCombat 订阅)。</summary>
public event System.Action<DamageInfo> OnHitConfirmed;
// 宿主投射物缓存Activate 时填入DamageInfo.SourceProjectile 写入用)
private Projectile _ownerProjectile;
/// <summary>
/// 激活 HitBox。source/attacker 均可选,未传则使用 Inspector 默认值。
/// ⚠️ 不存在 Activate(float duration) 重载。
@@ -86,6 +89,8 @@ namespace BaseGames.Combat
Debug.LogWarning($"[HitBox] {name}: Collider2D.isTrigger 应为 true。", this);
// 缓存 IClashServiceOnTriggerEnter2D 为物理热路径,避免每次调用 Dictionary 查找
_clashService = ServiceLocator.GetOrDefault<IClashService>();
// 缓存宿主投射物(仅 Projectile GameObject 上挂载的 HitBox 非 null
_ownerProjectile = GetComponent<Projectile>();
}
private void OnDisable()
@@ -124,7 +129,8 @@ namespace BaseGames.Combat
_currentSource,
knockDir,
_attackerTransform.position,
_attackerTransform.gameObject.layer);
_attackerTransform.gameObject.layer,
_ownerProjectile);
// ① 拼刀检测:当前 HitBox 携带 CanClash 标记,且碰到对立阵营的 HitBox 层
int otherLayer = other.gameObject.layer;

View File

@@ -64,7 +64,14 @@ namespace BaseGames.Combat
// 2. 弹反检查_parrySystem == null 时跳过)
// ParrySystem 只暴露窗口状态,伤害数据留在 Combat 层,无跨程序集数据依赖。
if (_parrySystem != null && info.Flags.HasFlag(DamageFlags.CanBeParried))
if (_parrySystem.ConsumeParry()) return;
{
if (_parrySystem.ConsumeParry())
{
// 若攻击来源是投射物,翻转其阵营 Layer 与飞行方向
info.SourceProjectile?.ReflectAsPlayerProjectile();
return;
}
}
// 3. 霸体检查_poiseSource == null 时跳过)
if (!info.Flags.HasFlag(DamageFlags.ForceBreak) && _poiseSource != null)

View File

@@ -51,7 +51,25 @@ namespace BaseGames.Combat
gameObject.layer = (ownerLayer == playerLayer) ? playerProjLayer : enemyProjLayer;
}
/// <summary>子类在此设定初速度或附加初始化逻辑。</summary>
/// <summary>
/// 弹反:将投射物阵营从 EnemyProjectile 切换为 PlayerProjectile。
/// 反转飞行方向,并重置 HitBox 命中记录使其能够命中新目标(敌人)。
/// 由 HurtBox.ReceiveDamage() 在弹反成功后调用。
/// </summary>
public virtual void ReflectAsPlayerProjectile()
{
int playerProjLayer = LayerMask.NameToLayer("PlayerProjectile");
if (playerProjLayer < 0) return;
gameObject.layer = playerProjLayer;
Direction = -Direction;
_rb.velocity = -_rb.velocity;
// 重置 HitBox 命中记录,确保反射后可命中新目标
_hitBox.Deactivate();
_hitBox.Activate(_config?.DamageSource);
}
protected virtual void OnInitialized() { }
protected virtual void Update()