Files
zeling_v2/Docs/Design/57_PhysicsLayerMatrix.md
2026-05-08 11:04:00 +08:00

14 KiB
Raw Permalink Blame History

57 · 物理层矩阵Physics Layer Matrix

命名空间 BaseGames.Physics(配置层)
所属文档集 ← 返回索引 · 总览
关联 04_CombatSystemHitBox/HurtBox· 06_EnemySystem · 13_ProjectileSystem · 24_GroundDetectionSystem · 40_LiquidSwimSystem


目录

  1. Layer 定义总表
  2. 碰撞矩阵Layer Collision Matrix
  3. Physics Material 目录
  4. Rigidbody2D 使用规范
  5. Trigger vs Collider 使用规范
  6. Layer 相关代码规范
  7. 常见错误与排查

1. Layer 定义总表

Unity 物理层Layer 0~31固定分配不允许随意挪用

Layer ID 名称 用途
0 Default 场景中无特殊需求的静态物件(不参与物理计算的装饰物)
1 TransparentFX Unity 内置,粒子特效(不参与碰撞)
2 Ignore Raycast Unity 内置,不参与任何 Raycast
3 (保留)
4 Water Unity 内置(本项目不使用,用 LiquidZone 代替)
5 UI Unity 内置UI 层
6 (保留)
7 (保留)
8 Ground 地面、平台(玩家/敌人站立的实体碰撞)
9 OneWayPlatform 单向平台(可从下方穿越,从上方落下后站立)
10 Wall 垂直墙壁(可抓附的墙体)
11 Hazard 伤害区域(荆棘/熔岩地面/毒液,无碰撞体阻挡,仅触发 Trigger
12 Player 玩家 Prefab 主体 Collider
13 PlayerHitBox 玩家攻击判定区HitBox
14 PlayerHurtBox 玩家受击区HurtBox
15 Enemy 敌人主体 Collider
16 EnemyHitBox 敌人攻击判定区HitBox
17 EnemyHurtBox 敌人受击区HurtBox
18 Projectile 弹射物玩家射出的子弹、Boss 弹幕)
19 EnemyProjectile 敌人弹射物(与 Projectile 分层,防止玩家弹射物误伤自己)
20 ParryTarget 可弹反的弹射物HurtBox 对 Parry 检测,见 05_ParrySystem
21 Interactable 可交互物件触发区IInteractable Trigger
22 LiquidZone 液态区域Trigger见 40_LiquidSwimSystem
23 AbilityGate 能力门触发区Trigger见 14_ProgressionSystem
24 Pickup 掉落物/收集品Trigger靠近自动吸附
25 Room 房间边界触发区Trigger触发场景加载/卸载)
26 CameraZone Cinemachine 约束区域Trigger不参与物理
27 VFX VFX 粒子(仅视觉,不参与碰撞)
28 NavMesh 寻路 AgentPathBerserker2d 专属,不与普通物理交互)
29 MagicWall 魔法障壁(Ghost 层忽略此层,实现太虚斩/地行术穿越)
30 Ghost 玩家施放太虚斩/地行术激活期间切换到此层;忽略 MagicWall 碰撞
31 PhantomBody 残阴术灵体 Rigidbody2D可触发 PhantomInteractable,忽略其余实体碰撞

2. 碰撞矩阵Layer Collision Matrix

= 相互检测碰撞 / Trigger 触发 | ─ = 忽略(不检测)

仅列出有意义的组合,其余均为

Ground OWPlatform Wall Hazard Player PlayerHB PlayerHurtB Enemy EnemyHB EnemyHurtB Projectile EnemyProj ParryTarget Interactable LiquidZone Pickup Room
Ground
OWPlatform
Wall
Hazard (T)
Player (T) (T) (T) (T) (T) (T) (T)
PlayerHitBox (T)
PlayerHurtBox (T) (T) (T)
Enemy (T)
EnemyHitBox (T)
EnemyHurtBox (T) (T)
Projectile (T) (T)
EnemyProjectile (T) (T)
ParryTarget

(T) = 仅 Trigger 检测OnTriggerEnter2D / OnTriggerStay2D不产生物理推力

新增层补充矩阵Ghost / MagicWall / PhantomBody

Ground OWPlatform Wall MagicWall Player Enemy Interactable PhantomInteractable
Ghost 忽略 (T) (T)
MagicWall
PhantomBody 忽略 忽略 忽略 忽略 (T)
  • Ghost:玩家变换为幽灵层后,与 MagicWall 无碰撞(穿越),但仍与地面/墙壁碰撞(地行术需要站在地面上遁行)。
  • PhantomBody:残阴术灵体完全忽略地面/墙壁,仅 Trigger 触发 PhantomInteractableInteractable 子层)。
  • SoftTerrain(松软地面)不需要独立物理层:使用 Ground 层,GroundDiveState 通过 Physics2D.OverlapPoint() 的返回值检查是否挂载 SoftTerrain 组件来判断地形类型。

矩阵关键设计决策

决策 原因
Enemy 不与 EnemyProjectile 碰撞 防止 Boss 弹幕打到自己身上
Projectile 不与 Enemy 碰撞(走 EnemyHurtBox 弹射物不推动敌人刚体,只通过 HurtBox 触发伤害
PlayerHitBox 不与 Ground/Wall 碰撞 防止近地攻击被地面碰撞遮挡
Hazard 只触发 Player,不触发 Enemy 敌人在自己的陷阱中不受伤
ParryTarget 不与任何层碰撞 弹反检测由 ParrySystemOverlapCircle 主动查询,无需被动碰撞

3. Physics Material 目录

存放路径:Assets/Physics/Materials/

资产名 Friction Bounciness 使用对象
PhysMat_Ground 0.4 0.0 地面碰撞体(普通地板)
PhysMat_Ice 0.02 0.0 冰面地块(低摩擦)
PhysMat_Bounce 0.2 0.8 弹跳蘑菇/弹射台
PhysMat_Player 0.0 0.0 玩家 Rigidbody2D Collider零摩擦防止卡墙
PhysMat_Enemy 0.3 0.0 敌人 Rigidbody2D Collider
PhysMat_Projectile 0.0 0.0 弹射物(与地面/墙壁碰撞时不反弹,由代码控制反弹逻辑)
PhysMat_Liquid 0.0 0.0 液态区域边界(仅 Trigger但 PhysMat 仍设为零摩擦)

摩擦力处理原则

  • 玩家碰撞体摩擦力始终为 0——移动完全由 PlayerMovement 的速度控制,不依赖物理摩擦
  • 坡面行走不依赖摩擦力,而是使用地面法线修正移动方向(见 24_GroundDetectionSystem.md
  • 弹跳效果不依赖 Bounciness 物理材质,而是在 OnCollisionEnter2D 中代码施加冲量(更可控)

4. Rigidbody2D 使用规范

对象类型 Body Type Interpolation Collision Detection Constraints
玩家 Dynamic Interpolate Continuous FreezeRotation Z
跟随平台(可移动地块) Kinematic Interpolate Continuous
普通敌人(地面) Dynamic Interpolate Discrete FreezeRotation Z
飞行敌人 Dynamic Interpolate Discrete FreezeRotation Z
弹射物 Dynamic None Continuous FreezeRotation Z
可破坏物件 Dynamic激活前 Kinematic None Discrete
触发区域Hazard/LiquidZone 等) 无 Rigidbody2D

禁止行为

  • 不在 Update() 中直接修改 transform.position(会绕过物理,用 Rigidbody2D.MovePosition
  • 不设置 Rigidbody2D.velocity 直接赋值(除非做瞬间冲刺,否则用 AddForce
  • 不在运行时频繁切换 Body TypeDynamic ↔ Kinematic 切换有性能开销)

5. Trigger vs Collider 使用规范

用途 使用 Collider 使用 Trigger
角色站立在地面上 Collider
HitBox / HurtBox 伤害检测 Trigger
危险区域(荆棘)伤害 Trigger
液态区域检测 Trigger
交互提示范围InteractionPrompt Trigger
房间边界(加载/卸载触发) Trigger
镜头约束区域Cinemachine ConfinerBound Collider设为 Trigger 二者并存(见 Cinemachine 文档)
弹射物与墙面碰撞(需反弹计算) Collider
弹射物与 HurtBox Trigger

混合使用(同一 Collider2D 同时作为 Collider 和 Trigger

  • 禁止——同一 Collider 不能同时是 Collider 和 Trigger语义混乱
  • 需要两种功能时,在同一 GameObject 上添加两个 Collider2D 组件

6. Layer 相关代码规范

6.1 使用 LayerMask 常量,禁止硬编码数字

// ✅ 正确
private static readonly int LayerGround = LayerMask.NameToLayer("Ground");
private static readonly LayerMask MaskGround = LayerMask.GetMask("Ground", "OneWayPlatform");

// ❌ 禁止
int layer = 8;  // 硬编码 Layer ID

6.2 统一 LayerMask 常量类

// Assets/Scripts/Core/Physics/Layers.cs
public static class Layers
{
    public static readonly int Ground         = LayerMask.NameToLayer("Ground");
    public static readonly int OneWayPlatform = LayerMask.NameToLayer("OneWayPlatform");
    public static readonly int Wall           = LayerMask.NameToLayer("Wall");
    public static readonly int Player         = LayerMask.NameToLayer("Player");
    public static readonly int PlayerHitBox   = LayerMask.NameToLayer("PlayerHitBox");
    public static readonly int PlayerHurtBox  = LayerMask.NameToLayer("PlayerHurtBox");
    public static readonly int Enemy          = LayerMask.NameToLayer("Enemy");
    public static readonly int EnemyHitBox    = LayerMask.NameToLayer("EnemyHitBox");
    public static readonly int EnemyHurtBox   = LayerMask.NameToLayer("EnemyHurtBox");
    public static readonly int Projectile     = LayerMask.NameToLayer("Projectile");
    public static readonly int EnemyProjectile = LayerMask.NameToLayer("EnemyProjectile");
    public static readonly int Hazard         = LayerMask.NameToLayer("Hazard");
    public static readonly int LiquidZone     = LayerMask.NameToLayer("LiquidZone");
    public static readonly int Pickup         = LayerMask.NameToLayer("Pickup");
    public static readonly int Room           = LayerMask.NameToLayer("Room");

    // 技能专属层
    public static readonly int Ghost        = LayerMask.NameToLayer("Ghost");       // 太虚斩/地行术幽灵层
    public static readonly int PhantomBody  = LayerMask.NameToLayer("PhantomBody"); // 残阴术灵体层
    public static readonly int MagicWall    = LayerMask.NameToLayer("MagicWall");   // 魔法障壁Ghost 穿越)

    // 复合 Mask常用组合
    public static readonly LayerMask MaskSolidGround   = LayerMask.GetMask("Ground", "OneWayPlatform");
    public static readonly LayerMask MaskWallAndGround = LayerMask.GetMask("Ground", "OneWayPlatform", "Wall");
    public static readonly LayerMask MaskAllHurtBox    = LayerMask.GetMask("PlayerHurtBox", "EnemyHurtBox");
    public static readonly LayerMask MaskEnemy         = LayerMask.GetMask("Enemy", "EnemyHurtBox");
    // Ghost 状态时的地面检测(排除 MagicWall但保留普通地面
    public static readonly LayerMask MaskGhostGround   = LayerMask.GetMask("Ground", "OneWayPlatform");
}

6.3 Layer 设置检查器CI 集成)

Assets/Tests/EditMode/PhysicsLayerTests.cs 中验证:

  • 所有 Layer 名称正确注册
  • Collision Matrix 中的关键对/忽略关系与本文档一致
  • 玩家 Prefab 使用正确的 Layer

7. 常见错误与排查

症状 原因 修复
玩家无法站在地面上 Player 与 Ground 的碰撞被关闭 检查 Collision Matrix
攻击打不到敌人 PlayerHitBox 与 EnemyHurtBox 碰撞关系未启用 勾选矩阵对应格
弹射物穿透地面 Projectile 的 Collision Detection 设为 Discrete 改为 Continuous
危险区域不造成伤害 Hazard 碰撞体忘记勾选 Is Trigger 勾选 Is Trigger
敌人被自己的弹幕打到 Enemy 与 EnemyProjectile 未忽略 检查矩阵,确认忽略
近地面攻击被地面碰撞打断 PlayerHitBox 与 Ground 未忽略 确认矩阵忽略该组合
单向平台两侧可以穿过 OneWayPlatform 应用了标准碰撞 使用 PlatformEffector2D 组件

本文档版本 1.0 · 2026-04 · 关联 04_CombatSystem / 13_ProjectileSystem / 24_GroundDetectionSystem