From dedd07e187c29e3d0ae19f17ab972bf3975c7fb7 Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Fri, 20 Feb 2026 21:27:53 +0800 Subject: [PATCH] =?UTF-8?q?Checkpoint=207=20=E6=B5=8B=E8=AF=95=E7=BB=93?= =?UTF-8?q?=E8=AE=BA=EF=BC=9A=20-=20TickEnemies=20=E6=9C=89=E6=98=8E?= =?UTF-8?q?=E6=98=BE=20GC=20=E5=A2=9E=E9=95=BF=EF=BC=8C=E4=B8=BB=E8=A6=81?= =?UTF-8?q?=E6=9D=A5=E8=87=AA=E6=A1=B6=E7=BB=93=E6=9E=84=E6=AF=8F=E5=B8=A7?= =?UTF-8?q?=E9=87=8D=E5=BB=BA=20-=20Simulation=20=E5=86=85=E6=A0=B8?= =?UTF-8?q?=E4=BB=8D=E7=9B=B4=E6=8E=A5=E4=BE=9D=E8=B5=96=20Transform?= =?UTF-8?q?=EF=BC=88=E4=B8=8D=E6=98=AF=E7=BA=AF=E6=95=B0=E6=8D=AE=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=EF=BC=89=20-=20=E5=BC=95=E5=85=A5=20P1.5=20=E6=9D=A5?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=B8=8A=E8=BF=B0=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=20P2=20=E8=BF=9B=E8=A1=8C=20Job=20=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E6=97=B6=E8=BF=94=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/Debugger/ProfilerMarker.cs | 1 + .../Scripts/Simulation/SimulationWorld.cs | 7 ++- Assets/Launcher.unity | 2 +- docs/P1 Simulation 分层.md | 43 +++++++++++++++++++ docs/TodoList.md | 43 ++++++++++++++++++- 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 docs/P1 Simulation 分层.md diff --git a/Assets/GameMain/Scripts/Debugger/ProfilerMarker.cs b/Assets/GameMain/Scripts/Debugger/ProfilerMarker.cs index 9a90e53..c1e4241 100644 --- a/Assets/GameMain/Scripts/Debugger/ProfilerMarker.cs +++ b/Assets/GameMain/Scripts/Debugger/ProfilerMarker.cs @@ -4,6 +4,7 @@ namespace CustomDebugger { public static class CustomProfilerMarker { + public static readonly ProfilerMarker TickEnemies = new ProfilerMarker("TickEnemies"); public static readonly ProfilerMarker Movement_Update = new ProfilerMarker("Movement_Update"); public static readonly ProfilerMarker ShopUI_Update = new("UGF.ShopUI.Update"); public static readonly ProfilerMarker Inventory_Refresh = new("UGF.Inventory.Refresh"); diff --git a/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs b/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs index 8f10a92..ecb27dd 100644 --- a/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs +++ b/Assets/GameMain/Scripts/Simulation/SimulationWorld.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using CustomDebugger; using CustomUtility; +using Unity.Profiling; using UnityEngine; using UnityGameFramework.Runtime; @@ -214,7 +216,10 @@ namespace Simulation return; } - TickEnemies(in context); + using (CustomProfilerMarker.TickEnemies.Auto()) + { + TickEnemies(in context); + } } public void Clear() diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity index 015ef5f..06b4865 100644 --- a/Assets/Launcher.unity +++ b/Assets/Launcher.unity @@ -1426,7 +1426,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8a558ebbc9cb4d94946ac9f4f27914d8, type: 3} m_Name: m_EditorClassIdentifier: - _useSimulationMovement: 0 + _useSimulationMovement: 1 --- !u!1 &1852670052 GameObject: m_ObjectHideFlags: 0 diff --git a/docs/P1 Simulation 分层.md b/docs/P1 Simulation 分层.md new file mode 100644 index 0000000..a7e56aa --- /dev/null +++ b/docs/P1 Simulation 分层.md @@ -0,0 +1,43 @@ +## 测试机性能 +iQOO Neo8 + +CPU: 第一代骁龙 8+ 八核 + +内存: 12 GB + +系统: OriginOS 6 (Android 16) + +## CPU +| 怪物数量 | 帧率 | TickEnemies 占比 | TickEnemies GC | Movement_Update 占比 | +|--------|-----------------------|--------------------|----------------|--------------------| +| `500` | `60.8 fps (16.43 ms)` | `37.6% (6.18 ms)` | `27.4 KB` | `0.0% (0 ms)` | +| `1000` | `40.2 fps (24.85 ms)` | `51.5% (12.8 ms)` | `54.5 KB` | `0.0% (0 ms)` | +| `1500` | `28.0 fps (35.62 ms)` | `56.4% (20.11 ms)` | `82.1 KB` | `0.0% (0 ms)` | +| `2000` | `18.8 fps (53.04 ms)` | `55.8% (29.62 ms)` | `107.6 KB` | `0.0% (0 ms)` | + +tip: +1. 60 fps 为 Android 端帧率上限,具体可参考 CPU ms 耗时 +2. 注意 Profiler 里会产生性能损耗的配置(Call Stacks) + +### Memory +| 怪物数量 | GC Used Memory | GC Allocated In Frame | +|------|----------------|-----------------------| +| 500 | 7.8 MB | 29.5 KB | +| 1000 | 8.8 MB | 56.6 KB | +| 1500 | 10.0 MB | 84.2 KB | +| 2000 | 11.8 MB | 109.7 KB | + + +### Render +| 维度 | 500 enemies | 1000 enemies | 1500 enemies | 2000 enemies | +|----------------------|-------------|--------------|--------------|--------------| +| SetPass Calls | 41 | 42 | 43 | 44 | +| Draw Calls | 46 | 46 | 48 | 49 | +| Batches | 46 | 46 | 48 | 49 | +| **Static Batching:** | | | | | +| Batched Draw Call | 0 | 0 | 0 | 0 | +| Batched | 0 | 0 | 0 | 0 | +| **Instancing:** | | | | | +| Batched Draw Call | 420 | 505 | 584 | 962 | +| Batched | 5 | 5 | 7 | 8 | + diff --git a/docs/TodoList.md b/docs/TodoList.md index 5932a70..695c682 100644 --- a/docs/TodoList.md +++ b/docs/TodoList.md @@ -60,7 +60,7 @@ - 先不迁移完整行为,只保证创建、回收、索引同步路径可用。 - 完成标准:投射物/掉落物实体生命周期正常,无索引越界与回收遗漏。 -- [ ] Checkpoint 7:P1 阶段回归与性能记录 +- [x] Checkpoint 7:P1 阶段回归与性能记录 - 回归用例:战斗 10 分钟、`Battle -> LevelUp -> Shop -> Battle` 循环、掉落吸附与拾取。 - Profiling 对比:记录 1k/2k/3k 敌人下 Main Thread、GC Alloc、敌人更新耗时。 - 输出文档:`P1 Simulation 分层设计 + 回滚开关说明 + 对比数据`。 @@ -69,6 +69,47 @@ **验收标准** - 敌人移动/追踪由 Simulation 统一调度,不再逐个 Enemy MonoBehaviour 执行核心逻辑。 +## 2.5 P1.5 Simulation 收尾(P2 前置) +- [ ] Checkpoint 1:清理 `TickEnemies` 侧 GC(优先级最高) + - 目标:将 `TickEnemies GC` 从当前 `27~108 KB` 降到 `< 5 KB / frame`。 + - 重点文件:`Assets/GameMain/Scripts/Utility/EnemySeperator/GridBucketEnemySeparationSolver.cs`。 + - 处理方式:桶容器与临时列表复用(包含 bucket list 复用池),避免每帧重建集合。 + - 完成标准:`2000` 敌人压测下 `TickEnemies GC` 稳定 `< 5 KB / frame`。 + +- [ ] Checkpoint 2:解耦 Simulation 核心与 `Transform` 运行时依赖 + - 目标:`SimulationWorld.TickEnemies` 不直接读取或写入 `Transform`。 + - 重点文件:`Assets/GameMain/Scripts/Simulation/SimulationWorld.cs`、`Assets/GameMain/Scripts/Utility/EnemySeperator/IEnemySeparationSolver.cs`、`Assets/GameMain/Scripts/Utility/EnemySeperator/EnemySeparationSolverProvider.cs`。 + - 处理方式:互斥求解输入改为纯数据(位置/半径/索引),`Transform` 仅在 Presentation 阶段回写。 + - 完成标准:`TickEnemies` 热路径中不出现 `Transform` 访问。 + +- [ ] Checkpoint 3:收口 `EntitySync` 职责边界 + - 目标:`EntitySync` 仅处理生命周期映射,不承担运行时移动逻辑。 + - 重点文件:`Assets/GameMain/Scripts/Simulation/SimulationWorld.EntitySync.cs`。 + - 处理方式:保留注册/反注册与初值同步,移除 Tick 过程依赖。 + - 完成标准:`OnShow/OnHide` 逻辑稳定,且不引入运行时分配热点。 + +- [ ] Checkpoint 4:拆分 Simulation Tick 阶段,为 Job 化铺路 + - 目标:将敌人 Tick 拆分为稳定阶段,便于后续迁移 `IJobParallelFor`。 + - 建议阶段:`BuildInput -> Move/Separation -> StateUpdate -> WriteBack`。 + - 重点文件:`Assets/GameMain/Scripts/Simulation/SimulationWorld.cs`。 + - 完成标准:每阶段有独立 `ProfilerMarker`,可明确观测耗时占比。 + +- [ ] Checkpoint 5:补最小回归测试(P1.5 重构保护) + - 目标:确保重构不改变战斗行为。 + - 建议目录:`Assets/Tests/Simulation/`。 + - 用例范围:追踪玩家、攻击距离停下、实体移除后的索引重映射。 + - 完成标准:EditMode/PlayMode 相关用例通过,主流程手测无回归。 + +- [ ] Checkpoint 6:补充 P1.5 结项文档 + - 输出:`P1.5 收尾说明 + 对比数据 + 回滚开关`。 + - 明确记录:Android 60fps 上限、Profiler 采样配置(Call Stacks 开关状态)、评估以 CPU ms 为主。 + - 完成标准:文档可复现实验结论,并可作为 P2 输入基线。 + +**验收标准** +- `Movement_Update` 持续维持 `0 ms`(或可忽略占比)。 +- `TickEnemies` 在目标敌人数下 GC 与 CPU 耗时均有明显下降,并可复现。 +- Simulation 层与表现层边界清晰,可无缝衔接 P2 Job/Burst 改造。 + ## 3. P2 Job System + Burst 落地(核心性能阶段) - [ ] 引入并锁定依赖版本(Unity 2022.3 对应): - `com.unity.collections`