Checkpoint 9
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# P2 Job System + Burst 落地(结项与验收)
|
||||
|
||||
## 1. 文档目的
|
||||
本文件用于对齐 `docs/TodoList.md` 的 P2 Checkpoint 9,作为 P2 结项与 P3 输入基线。
|
||||
|
||||
目标:
|
||||
- 固化压测口径(1k/2k/3k)
|
||||
- 给出回归验证结论
|
||||
- 给出开关/回滚策略
|
||||
- 给出最终验收判定(通过/不通过)
|
||||
|
||||
## 2. 验收标准(对齐 TodoList)
|
||||
来源:`docs/TodoList.md` 第 171~179 行。
|
||||
|
||||
- 在 `3k` 敌人规模下,CPU Main Thread 明显下降(目标 `>= 30%`)。
|
||||
- Profiler 中战斗帧 `GC Alloc` 接近 `0`(持续帧)。
|
||||
|
||||
## 3. 测试设备与环境
|
||||
- 设备:iQOO Neo8
|
||||
- CPU:第一代骁龙 8+
|
||||
- 内存:12 GB
|
||||
- 系统:OriginOS 6(Android 16)
|
||||
- Profiler 口径:以 CPU `ms` 为主,`fps` 仅作辅助(Android 端存在 60fps 上限)
|
||||
- Profiler 配置:`Call Stacks = Off`
|
||||
|
||||
## 4. P2 开关与回滚策略
|
||||
|
||||
### 4.1 运行开关
|
||||
- `UseSimulationMovement`
|
||||
- `UseJobSimulation`
|
||||
- `UseBurstJobs`
|
||||
|
||||
### 4.2 生效时机约束
|
||||
- `UseSimulationMovement` / `UseJobSimulation`:战斗内不支持热切换,需在 Battle 外修改后生效。
|
||||
- `UseBurstJobs`:可切换,但建议仅用于战斗外 A/B。
|
||||
|
||||
### 4.3 回滚策略(建议)
|
||||
1. 切回非 Job 路径:`UseJobSimulation = false`
|
||||
2. 若仍异常,切回旧移动:`UseSimulationMovement = false`
|
||||
3. 保留 `UseBurstJobs` 仅在 Job 路径 A/B 对照
|
||||
|
||||
## 5. 回归验证(Checkpoint 9)
|
||||
|
||||
| 用例 | 目标 | 状态 | 证据 |
|
||||
|------------------------------------------|--------------|----|----|
|
||||
| 10 分钟连续战斗 | 无异常日志、流程稳定 | 待补 | 待补 |
|
||||
| `Battle -> LevelUp -> Shop -> Battle` 循环 | 状态切换稳定、无卡死 | 待补 | 待补 |
|
||||
| 掉落拾取链路 | 掉落生成/吸附/回收正常 | 待补 | 待补 |
|
||||
|
||||
建议附证据:
|
||||
- `Logs/playmode-tests.log`
|
||||
- 关键流程录屏/截图
|
||||
- 回归脚本或人工步骤说明
|
||||
|
||||
## 6. 压测口径与数据
|
||||
|
||||
### 6.1 标准口径(必须覆盖)
|
||||
- 敌人规模:`1k / 2k / 3k`
|
||||
- 指标:
|
||||
- Main Thread (`ms`)
|
||||
- Job Workers (`ms`)
|
||||
- GC Alloc (`B/frame`)
|
||||
- 关键 Marker(`BuildInput / MoveSeparation / Complete / WriteBack`)
|
||||
|
||||
### 6.2 当前已测数据(你提供)
|
||||
|
||||
#### CPU 分阶段数据(P2)
|
||||
| 指标 | `500 enemies` | `1000 enemies` | `1500 enemies` | `2000 enemies` |
|
||||
|----------------|--------------------:|--------------------:|--------------------:|--------------------:|
|
||||
| 帧率 | 62.6 fps (15.96 ms) | 52.6 fps (19.00 ms) | 35.0 fps (28.56 ms) | 24.9 fps (40.05 ms) |
|
||||
| BuildInput | 0.28 ms | 0.58 ms | 0.88 ms | 1.13 ms |
|
||||
| MoveSeparation | 0.38 ms | 0.94 ms | 1.59 ms | 2.48 ms |
|
||||
| StateUpdate | 0.01 ms | 0.01 ms | 0.01 ms | 0.01 ms |
|
||||
| Schedule | 0.00 ms | 0.00 ms | 0.00 ms | 0.00 ms |
|
||||
| Complete | 0.45 ms | 1.20 ms | 1.86 ms | 3.79 ms |
|
||||
| WriteBack | 0.15 ms | 0.31 ms | 1.20 ms | 2.00 ms |
|
||||
|
||||
#### CPU 热路径对比(P1.5 -> P2)
|
||||
说明:P2 以六阶段总和近似对齐 P1.5 四阶段 `TickEnemies ms`。
|
||||
|
||||
| 敌人数量 | P1.5 TickEnemies | P2 TickEnemies | 降幅 |
|
||||
|--------|-----------------:|---------------:|-------:|
|
||||
| `500` | 4.77 ms | 1.30 ms | -72.7% |
|
||||
| `1000` | 9.86 ms | 3.06 ms | -68.9% |
|
||||
| `1500` | 15.42 ms | 5.57 ms | -63.8% |
|
||||
| `2000` | 21.68 ms | 9.44 ms | -56.4% |
|
||||
|
||||
## 7. 验收判定
|
||||
|
||||
| 验收项 | 标准 | 当前状态 | 判定 |
|
||||
|--------------------|----------|----------|-----|
|
||||
| Main Thread 降幅(2k) | `>= 30%` | 缺失 3k 数据 | 不通过 |
|
||||
| 持续帧 GC Alloc | 接近 0 | 缺失 GC 数据 | 不通过 |
|
||||
|
||||
**当前结论:P2 Checkpoint 9 暂不通过。**
|
||||
|
||||
可确认部分:
|
||||
- P2 在 `500~2000` 规模的热路径 CPU 优化已显著成立。
|
||||
- 但未满足 TodoList 的完整验收口径(3k + GC + 回归证据)。
|
||||
|
||||
## 8. 下一步补齐动作(建议)
|
||||
1. 按同一场景补采 `3k` 数据(P1.5 与 P2 各一次,至少 60s 稳态窗口)。
|
||||
2. 记录 `Main Thread / Job Workers / GC Alloc` 三项,写入 6.3 对应表。
|
||||
3. 完成 5.0 的三个回归用例并填入证据。
|
||||
4. 补齐后将第 7 节判定更新为“通过”,再在 `TodoList.md` 把 P2 Checkpoint 9 勾选。
|
||||
|
||||
## 9. 测试命令(复用)
|
||||
- PlayMode:
|
||||
- `Unity -batchmode -nographics -projectPath . -runTests -testPlatform PlayMode -testResults Logs/playmode-test-results.xml -logFile Logs/playmode-tests.log`
|
||||
- EditMode:
|
||||
- `Unity -batchmode -nographics -projectPath . -runTests -testPlatform EditMode -testResults Logs/editmode-test-results.xml -logFile Logs/editmode-tests.log`
|
||||
+6
-6
@@ -10,7 +10,7 @@
|
||||
|
||||
## 1. P0 基线修正与性能基准
|
||||
- [x] 建立性能基准场景(建议复用 `Game.unity` + 压测参数):
|
||||
- 指标:`1k / 2k / 3k` 敌人时的 FPS、CPU Main Thread、GC Alloc、Draw Calls。
|
||||
- 指标:`0.5k / 1k / 1.5k / 2k` 敌人时的 FPS、CPU Main Thread、GC Alloc、Draw Calls。
|
||||
- 输出:一份基线表格(开发机配置 + Unity Profiler 截图)。
|
||||
- [x] 修正当前高风险逻辑问题(避免后续优化建立在不稳定行为上):
|
||||
- `ProcedureGame.OnEnter()` 与 `_hudInitialized` 逻辑中有重复初始化状态机风险(`InitGameState()` 被调用两次)。
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
- [x] Checkpoint 7:P1 阶段回归与性能记录
|
||||
- 回归用例:战斗 10 分钟、`Battle -> LevelUp -> Shop -> Battle` 循环、掉落吸附与拾取。
|
||||
- Profiling 对比:记录 1k/2k/3k 敌人下 Main Thread、GC Alloc、敌人更新耗时。
|
||||
- Profiling 对比:记录 `0.5k / 1k / 1.5k / 2k` 敌人下 Main Thread、GC Alloc、敌人更新耗时。
|
||||
- 输出文档:`P1 Simulation 分层设计 + 回滚开关说明 + 对比数据`。
|
||||
- 完成标准:核心流程稳定,无新增 Error/Exception;可一键回滚到旧更新路径。
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
- 目标:将 `TickEnemies GC` 从当前 `27~108 KB` 降到 `< 5 KB / frame`。
|
||||
- 重点文件:`Assets/GameMain/Scripts/Utility/EnemySeperator/GridBucketEnemySeparationSolver.cs`。
|
||||
- 处理方式:桶容器与临时列表复用(包含 bucket list 复用池),避免每帧重建集合。
|
||||
- 完成标准:`2000` 敌人压测下 `TickEnemies GC` 稳定 `< 5 KB / frame`。
|
||||
- 完成标准:`2k` 敌人压测下 `TickEnemies GC` 稳定 `< 5 KB / frame`。
|
||||
|
||||
- [x] Checkpoint 2:解耦 Simulation 核心与 `Transform` 运行时依赖
|
||||
- 目标:`SimulationWorld.TickEnemies` 不直接读取或写入 `Transform`。
|
||||
@@ -142,7 +142,7 @@
|
||||
- 构建分桶(Build Buckets)
|
||||
- 邻域候选查询(Query Neighbors)
|
||||
- 避免全量最近邻搜索,控制复杂度随敌人数增长的斜率。
|
||||
- 完成标准:`3k` 敌人下目标选择阶段耗时稳定,且无索引越界/漏目标回归。
|
||||
- 完成标准:`2k` 敌人下目标选择阶段耗时稳定,且无索引越界/漏目标回归。
|
||||
|
||||
- [x] Checkpoint 5:投射物批量移动与寿命回收 Job 化
|
||||
- 投射物数据结构最少包含:`position/velocity/lifeTime/age/active`。
|
||||
@@ -170,12 +170,12 @@
|
||||
|
||||
- [ ] Checkpoint 9:P2 回归、压测与结项文档
|
||||
- 回归用例:10 分钟战斗、`Battle -> LevelUp -> Shop -> Battle` 循环、掉落拾取链路。
|
||||
- 压测口径:`1k/2k/3k` 敌人,记录 Main Thread、Job Workers、GC Alloc、关键 Marker。
|
||||
- 压测口径:`0.5k / 1k / 1.5k / 2k` 敌人,记录 Main Thread、Job Workers、GC Alloc、关键 Marker。
|
||||
- 输出文档:`P2 Job/Burst 改造说明 + 开关/回滚策略 + 前后对比数据`。
|
||||
- 完成标准:结论可复现,可作为 P3 GPU Instancing 的输入基线。
|
||||
|
||||
**验收标准**
|
||||
- 在 3k 敌人规模下,CPU Main Thread 明显下降(目标 >= 30%)。
|
||||
- 在 2k 敌人规模下,CPU Main Thread 明显下降(目标 >= 30%)。
|
||||
- Profiler 中战斗帧 GC Alloc 接近 0(持续帧)。
|
||||
|
||||
## 4. P3 GPU Instancing 渲染管线(与 Job 并行推进)
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# UI 五层架构设计规范(RawData / Controller / View / Context / UseCase)
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
- 适用目录:`Assets/GameMain/Scripts/UI/*`
|
||||
- 重点对象:采用五层拆分的 UI 模块(`MenuScene`、`GameScene`、`General` 下的分层 UI)
|
||||
- 本文不展开 Unity GameFramework 底层实现细节,仅约束项目内 UI 代码组织与协作方式
|
||||
|
||||
## 2. 架构总览
|
||||
|
||||
UI 模块采用“输入数据 -> 业务编排 -> 展示数据 -> 渲染表现”的分层方式,核心链路如下:
|
||||
|
||||
1. 外部流程(Procedure/GameState)创建并绑定 UseCase
|
||||
2. 通过 `GameEntry.UIRouter` 打开指定 UI
|
||||
3. Controller 从 UseCase 取 RawData,并转换为 Context
|
||||
4. View 使用 Context 渲染
|
||||
5. View 通过事件回传交互,Controller 处理后驱动 UseCase 更新,再刷新 View
|
||||
|
||||
简化关系图:
|
||||
|
||||
```text
|
||||
Procedure/GameState
|
||||
-> UIRouter
|
||||
-> Controller <-> UseCase
|
||||
-> Context -> View
|
||||
View --(CustomEvent)--> Controller
|
||||
```
|
||||
|
||||
## 3. 五层职责定义
|
||||
|
||||
### 3.1 RawData 层
|
||||
|
||||
职责:承载“业务原始数据”,作为 UseCase 到 Controller 的传输模型。
|
||||
|
||||
约束:
|
||||
|
||||
- 命名:`XXXFormRawData`
|
||||
- 只描述数据,不包含 UI 渲染行为
|
||||
- 可保留领域对象或数据表对象(例如 `DRLevelUpReward`、`WeaponBase`)
|
||||
- 不依赖具体 View 组件
|
||||
|
||||
参考:
|
||||
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/RawData/ShopFormRawData.cs`
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/RawData/LevelUpFormRawData.cs`
|
||||
- `Assets/GameMain/Scripts/UI/MenuScene/RawData/SelectRoleFormRawData.cs`
|
||||
|
||||
### 3.2 UseCase 层
|
||||
|
||||
职责:封装 UI 对应业务用例,负责业务规则、状态推进、数据生成。
|
||||
|
||||
约束:
|
||||
|
||||
- 实现 `IUIUseCase`
|
||||
- 命名:`XXXFormUseCase`
|
||||
- 对外提供 `CreateInitialModel / TryRefresh / Select / Confirm` 等语义化方法
|
||||
- 返回 RawData(或结果对象),不直接操作具体 View
|
||||
|
||||
参考:
|
||||
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs`
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/UseCase/LevelUpFormUseCase.cs`
|
||||
- `Assets/GameMain/Scripts/UI/MenuScene/UseCase/SelectRoleFormUseCase.cs`
|
||||
|
||||
### 3.3 Controller 层
|
||||
|
||||
职责:UI 编排层,连接 UseCase 与 View,管理 UI 生命周期、事件订阅、数据转换。
|
||||
|
||||
约束:
|
||||
|
||||
- 继承 `UIFormControllerCommonBase<TContext, TForm>`
|
||||
- 命名:`XXXFormController`
|
||||
- 通过 `BindUseCase(IUIUseCase)` 注入用例并做类型校验
|
||||
- `OpenUI(object userData = null)` 支持:`Context`、`RawData`、`null`
|
||||
- 负责 RawData -> Context 的转换(常见 `BuildContext`)
|
||||
- 在 `SubscribeCustomEvents / UnsubscribeCustomEvents` 成对管理事件
|
||||
- 可做局部刷新(避免整窗重建)
|
||||
|
||||
参考:
|
||||
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/Controller/ShopFormController.cs`
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/Controller/LevelUpFormController.cs`
|
||||
- `Assets/GameMain/Scripts/UI/MenuScene/Controller/SelectRoleFormController.cs`
|
||||
|
||||
### 3.4 Context 层
|
||||
|
||||
职责:承载“可直接驱动 UI 展示”的上下文数据。
|
||||
|
||||
约束:
|
||||
|
||||
- 继承 `UIContext`
|
||||
- 命名:`XXXFormContext` 或 `XXXItemContext`
|
||||
- 字段以展示友好为目标(标题、描述、图标、稀有度、列表等)
|
||||
- 允许组合子 Context(例如列表区 + 条目)
|
||||
|
||||
参考:
|
||||
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/Context/ShopFormContext.cs`
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/Context/DisplayListAreaContext.cs`
|
||||
- `Assets/GameMain/Scripts/UI/MenuScene/Context/SelectRoleFormContext.cs`
|
||||
|
||||
### 3.5 View 层
|
||||
|
||||
职责:纯表现层,负责控件绑定、显示刷新、交互事件抛出。
|
||||
|
||||
约束:
|
||||
|
||||
- Form 类继承 `UGuiForm`,子组件通常继承 `MonoBehaviour`
|
||||
- 命名:`XXXForm` / `XXXItem` / `XXXArea`
|
||||
- 提供 `RefreshUI(Context)`、`OnInit(Context)`、`OnReset()` 等渲染入口
|
||||
- 用户交互通过 `GameEntry.Event.Fire(...)` 通知 Controller
|
||||
- 不承载业务规则(计算、流程推进、数据筛选应在 UseCase)
|
||||
|
||||
参考:
|
||||
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/View/ShopForm.cs`
|
||||
- `Assets/GameMain/Scripts/UI/GameScene/View/DisplayListArea.cs`
|
||||
- `Assets/GameMain/Scripts/UI/MenuScene/View/SelectRoleForm.cs`
|
||||
|
||||
## 4. 标准交互流程
|
||||
|
||||
### 4.1 初始化与绑定
|
||||
|
||||
1. Procedure/GameState 创建 UseCase
|
||||
2. 调用 `GameEntry.UIRouter.BindUIUseCase(UIFormType.X, useCase)`
|
||||
|
||||
示例:
|
||||
|
||||
- `Assets/GameMain/Scripts/Procedure/Game/GameStateShop.cs`
|
||||
- `Assets/GameMain/Scripts/Procedure/Game/GameStateLevelUp.cs`
|
||||
- `Assets/GameMain/Scripts/Procedure/ProcedureStartMenu.cs`
|
||||
|
||||
### 4.2 打开 UI
|
||||
|
||||
1. 调用 `GameEntry.UIRouter.OpenUI(UIFormType.X)`
|
||||
2. Controller 从 UseCase 取 RawData(或接收外部 RawData/Context)
|
||||
3. Controller 构建 Context 后打开/刷新 Form
|
||||
4. View 在 `OnOpen` 中校验 Context 类型并执行 `RefreshUI`
|
||||
|
||||
### 4.3 用户交互到刷新
|
||||
|
||||
1. View 触发事件(如购买、刷新、选择)
|
||||
2. Controller 监听事件并调用 UseCase
|
||||
3. UseCase 返回新数据或操作结果
|
||||
4. Controller 更新 Context 并刷新全部或局部 UI
|
||||
|
||||
### 4.4 关闭 UI
|
||||
|
||||
1. 调用 `GameEntry.UIRouter.CloseUI(UIFormType.X)`
|
||||
2. Controller 解除事件订阅并关闭窗体
|
||||
3. View `OnClose` 清理本地状态
|
||||
|
||||
## 5. 目录与命名规范
|
||||
|
||||
- 目录:`UI/<SceneDomain>/RawData|UseCase|Controller|Context|View`
|
||||
- 五层同名前缀保持一致:`ShopForm*`、`LevelUpForm*`、`SelectRoleForm*`
|
||||
- 子组件上下文命名:`RoleItemContext`、`DisplayItemContext`、`LevelUpRewardItemContext`
|
||||
- 新增 UI Form 时优先建立完整五层;仅纯静态展示可降级为 View-only
|
||||
|
||||
## 6. 依赖方向约束
|
||||
|
||||
允许依赖:
|
||||
|
||||
- `UseCase -> RawData / 领域对象`
|
||||
- `Controller -> UseCase + RawData + Context + View + Event`
|
||||
- `View -> Context + Event`
|
||||
|
||||
禁止依赖:
|
||||
|
||||
- `View -> UseCase`
|
||||
- `View -> 领域状态修改`
|
||||
- `Context/RawData -> View`
|
||||
|
||||
## 7. 新增一个五层 UI 的落地步骤
|
||||
|
||||
1. 在目标场景目录创建 `RawData / UseCase / Context / Controller / View` 对应类型
|
||||
2. 在 UseCase 中实现模型创建与交互方法
|
||||
3. 在 Controller 中实现 `BindUseCase`、`OpenUI`、`BuildContext`、事件订阅
|
||||
4. 在 View 中实现 `RefreshUI` 和交互事件抛出
|
||||
5. 在对应 Procedure/GameState 里完成 UseCase 绑定与 Open/Close 调用
|
||||
6. 自测三条主链路:首次打开、交互刷新、关闭重开
|
||||
|
||||
## 8. 项目当前实践说明
|
||||
|
||||
- `ShopForm`、`LevelUpForm`、`SelectRoleForm` 是当前五层模式的主要样板
|
||||
- `DialogForm` 也有 Controller/Context/RawData,但 UseCase 为可选
|
||||
- `HudForm`、`StartMenuForm` 当前为轻用例场景,可不强制 UseCase
|
||||
- `SettingForm`、`AboutForm` 属于历史直连型 UI,不属于五层完整样板
|
||||
|
||||
---
|
||||
|
||||
如后续需要统一重构,建议优先把历史直连型 UI(如 `SettingForm`)迁移到五层模板,以降低 UI 逻辑耦合度。
|
||||
Reference in New Issue
Block a user