多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -84,17 +84,102 @@
> HitBox / HurtBox 依赖 Layer 碰撞矩阵,未配置时攻击不触发伤害。
**步骤**
1. 菜单 `Edit → Project Settings → Physics 2D`
2. 滚动到底部 **Layer Collision Matrix** 区域
3. 确认以下组合已勾选(绿色):
**详细配置步骤**
| 行 Layer | 列 Layer | 说明 |
1. 打开菜单 `Edit → Project Settings → Tags and Layers`
2. 在 User Layer 中创建以下 Layer名称必须完全一致区分大小写
| Layer 名称 | 用途 |
|-----------|------|
| `Player` | 玩家主物体Rigidbody2D 所在) |
| `Enemy` | 敌人主物体Rigidbody2D/导航代理所在) |
| `Ground` | 地面、墙体、平台等场景碰撞体 |
| `PlayerHitBox` | 玩家攻击判定触发器 |
| `PlayerHurtBox` | 玩家受击判定触发器 |
| `EnemyHitBox` | 敌人攻击判定触发器 |
| `EnemyHurtBox` | 敌人受击判定触发器 |
| `TriggerZone` | 存档点、相机区、剧情触发区 |
3. 给对象分配 LayerScene 中逐个核对):
| 对象 | Layer |
|------|-------|
| Player 根节点(含 Rigidbody2D | `Player` |
| Player/HitBox 子节点 | `PlayerHitBox` |
| Player/HurtBox 子节点 | `PlayerHurtBox` |
| Enemy 根节点(含 Rigidbody2D 或 NavAgent | `Enemy` |
| Enemy/HitBox 子节点(如果有) | `EnemyHitBox` |
| Enemy/HurtBox 子节点 | `EnemyHurtBox` |
| Tilemap Ground、静态障碍 | `Ground` |
| SavePoint、CameraTrigger、RoomTrigger | `TriggerZone` |
4. 打开菜单 `Edit → Project Settings → Physics 2D`
5. 滚动到底部 `Layer Collision Matrix`
6. 按 Unity `Layer Collision Matrix` 逐格设置(与你截图中的排列一致):
当前矩阵显示顺序(从上到下/从左到右)为:
| 序号 | Layer |
|------|-------|
| 0 | `Default` |
| 1 | `TransparentFX` |
| 2 | `Ignore Raycast` |
| 3 | `Player` |
| 4 | `Water` |
| 5 | `UI` |
| 6 | `Enemy` |
| 7 | `Ground` |
| 8 | `PlayerHitBox` |
| 9 | `PlayerHurtBox` |
| 10 | `EnemyHitBox` |
| 11 | `EnemyHurtBox` |
| 12 | `TriggerZone` |
在该排列下,只需要重点修改以下交叉格(其余保持默认即可):
| 行 Layer | 列 Layer | 设置 |
|---------|---------|------|
| `PlayerHitBox` | `EnemyHurtBox` | 玩家攻击打敌人 |
| `EnemyHitBox` | `PlayerHurtBox` | 敌人攻击打玩家 |
| `Player` | `Ground` | 玩家落地检测 |
| `Enemy` | `Ground` | 敌人落地检测 |
| `Player` | `Ground` | ✅ |
| `Enemy` | `Ground` | ✅ |
| `Player` | `Enemy` | ✅ |
| `PlayerHitBox` | `EnemyHurtBox` | ✅ |
| `EnemyHitBox` | `PlayerHurtBox` | ✅ |
| `TriggerZone` | `Player` | ✅ |
| `PlayerHitBox` | `Ground` | ❌ |
| `EnemyHitBox` | `Ground` | ❌ |
| `PlayerHurtBox` | `Ground` | ❌ |
| `EnemyHurtBox` | `Ground` | ❌ |
| `PlayerHitBox` | `PlayerHurtBox` | ❌ |
| `EnemyHitBox` | `EnemyHurtBox` | ❌ |
| `PlayerHitBox` | `Player` | ❌ |
| `EnemyHitBox` | `Enemy` | ❌ |
| `TriggerZone` | `Enemy` | ❌ |
定位技巧(与 Unity 面板一致):
- Unity 只显示下三角矩阵,`A × B``B × A` 是同一个格
- 找不到某一格时,优先在“行名较靠下”的那一行里找对应列
- 先设置 5 个核心开启项:`Player-Ground``Enemy-Ground``PlayerHitBox-EnemyHurtBox``EnemyHitBox-PlayerHurtBox``TriggerZone-Player`
7. 组件级别补充设置(和矩阵一起生效):
- HitBox 与 HurtBox 的 Collider2D 必须 `Is Trigger = true`
- Player/Enemy 主体 Collider2D 必须 `Is Trigger = false`
- 至少一方需要 Rigidbody2D 才会触发 Trigger 回调(本项目通常在主体根节点)
8. 快速验证:
- 玩家攻击敌人:应触发 `EVT_HitConfirmed`
- 敌人攻击玩家:玩家 HP 下降且 HUD 刷新
- 玩家接触 SavePoint应触发 `EVT_SavePointActivated`
### 1.6 本文统一测试场景与加载方式(必须按此执行)
为避免“服务层未加载”或“房间场景缺对象”的误判,本文所有验证默认使用以下场景组合:
1. 打开 `Assets/Scenes/Persistent.unity`
2. 使用 Additive 方式再打开 `Assets/Scenes/TestRoom.unity`
3. 在 Hierarchy 中确认 `Persistent``TestRoom` 两个场景同时处于已加载状态
4. 若当前只开了 `TestRoom.unity`,请先停止测试并改为上述双场景组合后再执行
> 例外:仅测试单纯美术或单房间静态内容时可只开 `TestRoom.unity`。但凡涉及输入、服务注册、事件总线、存档、死亡复活,必须使用双场景组合。
---
@@ -148,7 +233,7 @@
_deathScreenController → DeathScreenController GameObject 引用
```
### 2.2 测试房间场景 —— `Assets/Scenes/Rooms/TestRoom.unity`
### 2.2 测试房间场景 —— `Assets/Scenes/TestRoom.unity`
```
[TestRoom]
@@ -222,12 +307,21 @@
## 3. 编辑器扩展工具一览
Phase 0/1 实现了以下 Editor-only 工具,验证过程中会频繁用到
当前验证会用到两类入口
1. **BaseGames 自定义菜单工具**:会出现在 `BaseGames` 菜单下
2. **Unity / 第三方现成窗口**:仍然在各自原生菜单里,不会出现在 `BaseGames` 菜单下
| 工具 | 菜单路径 | 快捷键 | 用途 |
|------|---------|--------|------|
| **Event Bus Monitor** | `BaseGames → Tools → Event Bus Monitor` | `Ctrl+Shift+E` | Play 模式下实时查看所有 SO 事件触发记录 |
| **Validate AddressKeys** | `Tools → Validate AddressKeys` | — | 手动校验 AddressKeys 常量与 Addressable 分组一致性 |
| **Create Event Channel Assets** | `BaseGames → Tools → Create Event Channel Assets` | — | 一键生成全局事件频道资产 |
| **Reimport Event Channel Assets** | `BaseGames → Tools → Reimport Event Channel Assets` | — | 批量重导入 `Assets/Data/Events` 下的事件资产 |
| **Validate Address Keys** | `BaseGames → Tools → Validate Address Keys` | — | 手动校验 AddressKeys 常量与 Addressable 分组一致性 |
| **Scaffold Persistent Scene** | `BaseGames → Tools → Scaffold Persistent Scene` | — | 一键生成 Persistent 场景基础层级与核心组件骨架 |
| **Scaffold Test Room** | `BaseGames → Tools → Scaffold Test Room` | — | 一键生成 TestRoom 基础层级、Player/Enemy/Camera/SavePoint 骨架 |
| **Apply Script Execution Order Preset** | `BaseGames → Tools → Apply Script Execution Order Preset` | — | 一键写入推荐的脚本执行顺序 |
| **Validate Script Execution Order Preset** | `BaseGames → Tools → Validate Script Execution Order Preset` | — | 校验当前执行顺序是否符合推荐值 |
| **Animancer Window** | `Window → Animation → Animancer` | — | 查看当前播放的动画状态和混合树 |
| **Behavior Designer** | 选中敌人 → Inspector → Open | — | 实时观察 BT 节点执行路径 |
| **Audio Mixer** | `Window → Audio → Audio Mixer` | — | 查看实时音频电平 |
@@ -246,8 +340,10 @@ Phase 0/1 实现了以下 Editor-only 工具,验证过程中会频繁用到:
#### 步骤 1确认执行顺序配置
1. 菜单 `Edit → Project Settings → Script Execution Order`
2. 确认以下顺序存在(数字越小越先执行):
1. 优先使用一键菜单`BaseGames → Tools → Apply Script Execution Order Preset`
2. (可选)执行校验菜单:`BaseGames → Tools → Validate Script Execution Order Preset`
3. 若需人工复核,打开 `Edit → Project Settings → Script Execution Order`
4. 确认以下顺序存在(数字越小越先执行):
| 脚本 | ExecutionOrder |
|------|---------------|
@@ -260,7 +356,7 @@ Phase 0/1 实现了以下 Editor-only 工具,验证过程中会频繁用到:
#### 步骤 2Play 模式验证
1. 打开包含 `Persistent.unity` 的场景
1. 按 [1.6 本文统一测试场景与加载方式](#16-本文统一测试场景与加载方式必须按此执行) 加载 `Persistent.unity + TestRoom.unity`
2.**Play**
3. 查看 Console预期输出顺序
```
@@ -381,7 +477,21 @@ ISceneService: SceneService
**验证目标**:物理按键正确映射到 InputReaderSO 事件InputBuffer 缓冲窗口生效。
#### 步骤 1Inspector 字段核查
#### 步骤 0先进入正确场景必做
1. 按 [1.6 本文统一测试场景与加载方式](#16-本文统一测试场景与加载方式必须按此执行) 加载场景
2. 打开 `BaseGames → Tools → Event Bus Monitor`
3. 在 EventBusMonitorWindow 点击 **Clear** 清空历史记录
4. 在 Filter 输入框输入 `Pause`
#### 步骤 1InputReader 挂载与引用核查
1.`Persistent` 场景中选中 `InputReaderHolder`
2. 检查 `InputReaderBootstrap._inputReader`:必须已拖拽 `Assets/Data/Input/InputReader.asset`
3. 检查 `InputReader.asset`ScriptableObject中的 `_inputActions`:必须指向 `Assets/Settings/PlayerInputActions.inputactions`
4. 检查 `_onPauseRequested`:必须指向 `Assets/Data/Events/EVT_PauseRequested.asset`
#### 步骤 2Inspector 字段核查
选中 `InputBuffer` 组件(挂在 Player 上):
@@ -392,18 +502,40 @@ ISceneService: SceneService
| `_attackBufferDuration` | **0.12** |
| `_dashBufferDuration` | **0.10** |
#### 步骤 2InputActions 配置验证
#### 步骤 3InputActions 配置验证
1. 双击 `Assets/Settings/PlayerInputActions.inputactions` 打开 Input System 编辑器
2. 确认以下 **Action Maps** 存在:
- `Gameplay`(含 Move / Jump / Attack / Dash / Parry 等 Actions
- `UI`(含 Navigate / Submit / Cancel
- `Cutscene`(含 Skip 等)
3. 检查 `Jump` Action 的 Binding
- `Gameplay`(含 Move / Jump / Attack / DownAttack / UpAttack / Parry / Dash / UseSpring / Switch* / SoulSkill / SpiritSkill* / Interact / Pause
- `UI`(含 Navigate / Submit / Cancel / Pause / Point
3. 检查 `Pause` Action 的 BindingGameplay 与 UI 均需存在):
- `Keyboard``Escape`
- `Gamepad``Start`
4. 检查 `Jump` Action 的 Binding
- `Keyboard``Space`
- `Gamepad``Button South`(南键)
#### 步骤 3缓冲窗口验证跳跃缓冲
#### 步骤 4Escape 事件链验证(本阶段主验证项
1.**Play**
2. 按一次 `Escape`
3. 观察 Console必须出现一次链路日志
```
[InputReaderSO.HandlePause] PAUSE INPUT DETECTED!
[InputReaderSO.HandlePause] Invoking PauseEvent...
[InputReaderSO.HandlePause] Raising _onPauseRequested channel...
```
4. 观察 EventBusMonitorWindowFilter=Pause
- 应新增 1 条 `EVT_PauseRequested`
- `Subs` 应大于 0通常为 2
5. 再按一次 `Escape`
6. 再次确认仅新增 1 条 `EVT_PauseRequested`
> 通过标准:按 2 次 Escape新增 2 条 `EVT_PauseRequested`。若出现 4 条,表示重复绑定回归,需要排查 InputReaderSO 的重复 Bind。
#### 步骤 5缓冲窗口验证跳跃缓冲
1. 让玩家跳跃到空中
2. **在落地前约 100150ms**(目测约 35 帧前)按下跳跃键