完整启动流程

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

@@ -58,7 +58,13 @@
|---|---|---|
| `TriggerZone` | 存档点(`CheckpointMarker`)、存档台(`SavePoint`)、传送站(`TeleportStation`)、房间过渡(`RoomTransition` / `DoorTransition`)、相机区域(`CameraArea` | 纯触发碰撞体isTrigger不参与物理阻挡统一使用此 Layer 方便在碰撞矩阵中集中管理 |
### 2.5 特殊用途
### 2.5 环境危险
| Layer 名称 | 挂载对象 | 用途说明 |
|---|---|---|
| `HazardHitBox` | 对双方均造成伤害的环境危险落石、熔岩、毒区、AOE 爆炸范围等) | 同时与 `PlayerHurtBox``EnemyHurtBox` 碰撞;区别于 `EnemyHitBox`(只对玩家),此 Layer 用于阵营中立的环境伤害源 |
### 2.6 特殊用途
| Layer 名称 | 挂载对象 | 用途说明 |
|---|---|---|
@@ -85,6 +91,10 @@
| `EnemyProjectile` | `Ground` | ✅ | 敌人投射物命中地形 |
| `PlayerHitBox` | `PlayerHurtBox` | ❌ | 玩家不自伤 |
| `PlayerProjectile` | `EnemyProjectile` | ❌ | 子弹不互相碰撞Clash 系统单独处理) |
| `HazardHitBox` | `PlayerHurtBox` | ✅ | 环境危险伤害玩家 |
| `HazardHitBox` | `EnemyHurtBox` | ✅ | 环境危险伤害敌人(中立伤害) |
| `HazardHitBox` | `PlayerHitBox` | ❌ | 环境不触发拼刀 |
| `HazardHitBox` | `EnemyHitBox` | ❌ | 环境不触发拼刀 |
> 未在上表中列出的 Layer 对默认继承 Unity 全局设置(默认全部碰撞)。
@@ -122,7 +132,83 @@ void Awake()
---
## 5. 检查与修复工具
## 6. 复杂场景处理模式
### 6.1 弹反投射物EnemyProjectile → 伤害敌人)
**问题**`EnemyProjectile ↔ EnemyHurtBox = 不碰撞`,弹反后的投射物无法对敌人造成伤害。
**正确方案:运行时 Layer 切换**(不新增 Layer
弹反成功时,将投射物的 Layer 从 `EnemyProjectile` 切换为 `PlayerProjectile`,同时反转飞行方向。`Projectile` 已有 `SetFactionLayer(int ownerLayer)` 方法,弹反逻辑只需调用它:
```csharp
// HurtBox.ReceiveDamage() 弹反成功后步骤2
if (_parrySystem.ConsumeParry())
{
// 若攻击来源是投射物,翻转其阵营 Layer
if (info.SourceProjectile != null)
{
info.SourceProjectile.ReflectAsPlayerProjectile();
// ReflectAsPlayerProjectile() 内部:
// gameObject.layer = LayerMask.NameToLayer("PlayerProjectile");
// rb.velocity = -rb.velocity; // 反向
}
return;
}
```
> **注意**:当前 `DamageInfo` 尚未携带 `SourceProjectile` 字段,实现此功能需要:
> 1. 在 `DamageInfo` 中添加 `Projectile SourceProjectile` 字段
> 2. `HitBox.OnTriggerEnter2D` 通过 `_attackerTransform.GetComponent<Projectile>()` 填入
> 3. `Projectile` 实现 `ReflectAsPlayerProjectile()` 方法
**为什么不新建 `ParriedProjectile` 层?**
`PlayerProjectile` 的语义本就是"对敌人有效、对玩家无效"的攻击来源,弹反后的投射物完全符合此语义,无需新层。
---
### 6.2 环境伤害(同时对玩家与敌人有效)
`LethalTrap`(陷阱)当前使用 `EnemyHitBox` 层,只对玩家生效,是**有意为之**的设计(跑酷陷阱不伤敌人)。
对于确实需要**同时伤害双方**的环境机关落石、熔岩、AOE 区域等),使用 `HazardHitBox` 层并配合 `HazardHitBoxTrigger` 组件(待实现),收到碰撞时向 `PlayerHurtBox``EnemyHurtBox` 均发送伤害:
```
HazardHitBox ↔ PlayerHurtBox → 碰撞
HazardHitBox ↔ EnemyHurtBox → 碰撞
```
---
### 6.3 敌人之间互伤(友伤/AOE
`EnemyHitBox ↔ EnemyHurtBox = 碰撞` 已在碰撞矩阵中开启。
自伤防护由 `HitBox.OnTriggerEnter2D` 的根节点比较负责:
```csharp
if (other.transform.root == _attackerTransform.root) return; // 排除自身
```
这意味着:
- 同一 GameObject 树的 EnemyHitBox 不会命中自身的 EnemyHurtBox ✅
- 敌人 A 的 HitBox 可以命中敌人 B 的 HurtBox ✅(天然支持友伤)
- Boss 的 AOE 技能可以对场景中所有其他敌人造成伤害 ✅
---
### 6.4 不需要细分的场景
以下场景**不需要新增 Layer**,通过 `DamageInfo` 字段在逻辑层区分即可:
| 场景 | 处理方式 |
|---|---|
| 区分攻击来源(玩家技能 vs 玩家普攻) | `DamageInfo.SkillId` / `DamageInfo.SourceId` |
| 不同类型伤害(物理 vs 魔法) | `DamageInfo.Type``DamageType` 枚举) |
| Boss 阶段专属伤害规则 | `DamageInfo.Tags``DamageTags` 标记位) |
| 不可弹反的攻击 | `DamageInfo.Flags` 不含 `CanBeParried` |
| 穿透无敌帧的伤害 | `DamageInfo.Flags``IgnoreIFrame` |
项目提供了 **Physics2DLayerReport** 编辑器工具,位于菜单: