- Checkpoint 1:清理 TickEnemies 侧 GC
- Checkpoint 2:解耦 Simulation 核心与 `Transform` 运行时依赖 - Checkpoint 3:收口 `EntitySync` 职责边界 - Checkpoint 4:拆分 Simulation Tick 阶段 - Checkpoint 5:补最小回归测试 - Checkpoint 6:补充 P1.5 结项文档
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# P1.5 Simulation 收尾说明(P2 输入基线)
|
||||
|
||||
## 测试设备与环境
|
||||
- 设备:iQOO Neo8
|
||||
- CPU:第一代骁龙 8+ 八核
|
||||
- 内存:12 GB
|
||||
- 系统:OriginOS 6(Android 16)
|
||||
- Unity Profiler 口径:以 CPU `ms` 为主,`fps` 仅作辅助(Android 端 60 fps 上限)
|
||||
- Profiler 配置:`Call Stacks = Off`(开启会额外放大 CPU 开销,不纳入本次基线)
|
||||
|
||||
## CPU 分阶段数据(P1.5)
|
||||
| 怪物数量 | 帧率 | MoveSeperation 占比 | BuildInput 占比 | WriteBack 占比 | StateUpdate 占比 |
|
||||
|--------|---------------------|--------------------|------------------|------------------|------------------|
|
||||
| `500` | `60 fps (16.56 ms)` | `25.8% (4.28 ms)` | `1.2% (0.20 ms)` | `1.0% (0.17 ms)` | `0.7% (0.12 ms)` |
|
||||
| `1000` | `44 fps (22.77 ms)` | `38.9% (8.86 ms)` | `1.8% (0.41 ms)` | `1.5% (0.36 ms)` | `1.0% (0.23 ms)` |
|
||||
| `1500` | `33 fps (29.83 ms)` | `46.7% (13.95 ms)` | `2.0% (0.61 ms)` | `1.7% (0.51 ms)` | `1.1% (0.35 ms)` |
|
||||
| `2000` | `19 fps (53.04 ms)` | `43.1% (19.53 ms)` | `2.1% (0.97 ms)` | `1.5% (0.69 ms)` | `1.0% (0.49 ms)` |
|
||||
|
||||
## Memory 对比(P1 -> P1.5)
|
||||
| 怪物数量 | GC Used Memory | GC Allocated In Frame | TickEnemies GC |
|
||||
|--------|------------------|-----------------------|-----------------|
|
||||
| `500` | `7.8 -> 7.9 MB` | `29.5 -> 2.1 KB` | `27.4 -> 0 KB` |
|
||||
| `1000` | `8.8 -> 8.8 MB` | `56.6 -> 2.1 KB` | `54.5 -> 0 KB` |
|
||||
| `1500` | `10.0 -> 9.0 MB` | `84.2 -> 2.1 KB` | `82.1 -> 0 KB` |
|
||||
| `2000` | `11.8 -> 9.9 MB` | `109.7 -> 2.1 KB` | `107.6 -> 0 KB` |
|
||||
|
||||
## CPU 热路径对比(P1 -> P1.5)
|
||||
说明:P1.5 的 `TickEnemies` 以四阶段总和近似对齐 P1 的 `TickEnemies ms`。
|
||||
|
||||
| 怪物数量 | P1 TickEnemies | P1.5 四阶段合计 | 降幅 |
|
||||
|--------|----------------|------------|----------|
|
||||
| `500` | `6.18 ms` | `4.77 ms` | `-22.8%` |
|
||||
| `1000` | `12.80 ms` | `9.86 ms` | `-23.0%` |
|
||||
| `1500` | `20.11 ms` | `15.42 ms` | `-23.3%` |
|
||||
| `2000` | `29.62 ms` | `21.68 ms` | `-26.8%` |
|
||||
|
||||
## 结论(Checkpoint 6)
|
||||
- GC 目标达成:`TickEnemies GC` 在 `500~2000` 敌人数下均为 `0 KB`,满足 `< 5 KB/frame` 目标。
|
||||
- CPU 阶段可观测性达成:`BuildInput -> Move/Separation -> StateUpdate -> WriteBack` 已可稳定采样。
|
||||
- 当前主瓶颈明确:`MoveSeperation` 是绝对热点(约 `43%~47%` 帧占比),P2 优先并行化该阶段。
|
||||
- 评估口径可复现:Android 端受 `60 fps` 上限影响,性能判断以 CPU `ms` 为准。
|
||||
|
||||
## 回滚开关说明
|
||||
- 开关字段:`SimulationWorld._useSimulationMovement`(序列化私有字段)
|
||||
- 对外接口:`UseSimulationMovement` / `SetUseSimulationMovement(bool)`
|
||||
- 回滚方式:将开关置 `false`,敌人立即回退到旧 `MovementComponent` 更新路径。
|
||||
- 验证建议:同场景同刷怪参数下执行 A/B 对比,确认行为一致与性能差异。
|
||||
|
||||
## P2 交接建议
|
||||
- Job/Burst 第一优先级:`MoveSeperation` 阶段并行化。
|
||||
- 保持阶段边界不变:继续维持四阶段管线与 `ProfilerMarker`,避免失去对比口径。
|
||||
- 保持生命周期/索引规则不变:`EntitySync` 与 swap-back/remap 继续作为硬约束。
|
||||
+7
-6
@@ -70,37 +70,37 @@
|
||||
- 敌人移动/追踪由 Simulation 统一调度,不再逐个 Enemy MonoBehaviour 执行核心逻辑。
|
||||
|
||||
## 2.5 P1.5 Simulation 收尾(P2 前置)
|
||||
- [ ] Checkpoint 1:清理 `TickEnemies` 侧 GC(优先级最高)
|
||||
- [x] 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` 运行时依赖
|
||||
- [x] 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` 职责边界
|
||||
- [x] Checkpoint 3:收口 `EntitySync` 职责边界
|
||||
- 目标:`EntitySync` 仅处理生命周期映射,不承担运行时移动逻辑。
|
||||
- 重点文件:`Assets/GameMain/Scripts/Simulation/SimulationWorld.EntitySync.cs`。
|
||||
- 处理方式:保留注册/反注册与初值同步,移除 Tick 过程依赖。
|
||||
- 完成标准:`OnShow/OnHide` 逻辑稳定,且不引入运行时分配热点。
|
||||
|
||||
- [ ] Checkpoint 4:拆分 Simulation Tick 阶段,为 Job 化铺路
|
||||
- [x] Checkpoint 4:拆分 Simulation Tick 阶段,为 Job 化铺路
|
||||
- 目标:将敌人 Tick 拆分为稳定阶段,便于后续迁移 `IJobParallelFor`。
|
||||
- 建议阶段:`BuildInput -> Move/Separation -> StateUpdate -> WriteBack`。
|
||||
- 重点文件:`Assets/GameMain/Scripts/Simulation/SimulationWorld.cs`。
|
||||
- 完成标准:每阶段有独立 `ProfilerMarker`,可明确观测耗时占比。
|
||||
|
||||
- [ ] Checkpoint 5:补最小回归测试(P1.5 重构保护)
|
||||
- [x] Checkpoint 5:补最小回归测试(P1.5 重构保护)
|
||||
- 目标:确保重构不改变战斗行为。
|
||||
- 建议目录:`Assets/Tests/Simulation/`。
|
||||
- 用例范围:追踪玩家、攻击距离停下、实体移除后的索引重映射。
|
||||
- 完成标准:EditMode/PlayMode 相关用例通过,主流程手测无回归。
|
||||
|
||||
- [ ] Checkpoint 6:补充 P1.5 结项文档
|
||||
- [x] Checkpoint 6:补充 P1.5 结项文档
|
||||
- 输出:`P1.5 收尾说明 + 对比数据 + 回滚开关`。
|
||||
- 明确记录:Android 60fps 上限、Profiler 采样配置(Call Stacks 开关状态)、评估以 CPU ms 为主。
|
||||
- 完成标准:文档可复现实验结论,并可作为 P2 输入基线。
|
||||
@@ -190,3 +190,4 @@
|
||||
- [ ] 回归用例(至少战斗、关卡切换、商店、升级)。
|
||||
- [ ] Profiling 对比(改造前后同场景同参数)。
|
||||
- [ ] 风险与回滚说明(特别是热更新与渲染链路)。
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
# Weapon Development Skill(VampireLike)
|
||||
|
||||
## 目标
|
||||
本文件是 `Entity.Weapon` 体系的开发规范与速查手册。
|
||||
后续新增武器或扩展机制时,优先按本文档执行,避免重复通读历史上下文。
|
||||
|
||||
## 当前架构总览
|
||||
- 武器运行时入口:`WeaponBase`(`Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs`)
|
||||
- 武器具体实现:`WeaponKnife`、`WeaponHandgun`、`WeaponSlash`
|
||||
- 目标选择策略:`ITargetSelector` + `TargetSelectorType`
|
||||
- 攻击可视化:`IWeaponAttackEffect`
|
||||
- 数据入口:`DRWeapon` -> `WeaponData`(及其子类)
|
||||
- 实体生成:`EntityExtension.ShowWeapon`
|
||||
|
||||
## WeaponBase 统一职责(已上收)
|
||||
`WeaponBase` 负责以下通用逻辑,子类不要重复实现:
|
||||
- 生命周期模板:`OnShow/OnHide/OnAttachTo/OnDetachFrom`
|
||||
- 状态机管理:`RegisterState`、`EnsureStatesBuilt`、`TransitionTo`
|
||||
- 通用运行字段:`_target`、`_currAttackTimer`、`_sqrRange`
|
||||
- 启用门控:`OnUpdate` 中统一 `if (!_isEnabled) return`
|
||||
- 目标选择入口:`SelectTarget`、`SetTargetSelector`、`CreateSelector`
|
||||
- 距离判定:`IsInRange`(基于 XZ 平面距离)
|
||||
- 玩家攻击属性订阅:`BindAttackStatFromOwner` / `ReleaseAttackStatSubscription`
|
||||
|
||||
## 状态机约定
|
||||
统一状态枚举:
|
||||
- `Idle`
|
||||
- `Check_OutRange`
|
||||
- `Check_InRange`
|
||||
- `Attack`
|
||||
- `Disabled`(可选)
|
||||
|
||||
推荐流程:
|
||||
1. `Idle`:查找目标,计时器持续累积。
|
||||
2. `Check_OutRange`:有目标但不在攻击范围,继续转向并累积计时。
|
||||
3. `Check_InRange`:在攻击范围内,若 `currAttackTimer >= Cooldown` 切 `Attack`。
|
||||
4. `Attack`:执行攻击,重置计时器,结束后回 `Check_InRange`。
|
||||
|
||||
关键规则:
|
||||
- 即使没有目标,也允许蓄力(计时器持续走)。
|
||||
- 一旦进入 `Check_InRange` 且冷却已满,应立即触发攻击。
|
||||
|
||||
## 3D 场景下的距离/朝向原则
|
||||
- 射程与目标筛选:优先使用 XZ 平面距离(忽略 Y),调用 `AIUtility.GetSqrMagnitudeXZ`。
|
||||
- 视觉朝向与弹道:可按武器设计决定是否使用完整 3D 向量。
|
||||
- `WeaponHandgun`:允许俯仰瞄准,逻辑上用射线命中对象判定伤害。
|
||||
- 近战地面范围类(Knife/Slash):伤害检测建议投影到地面(XZ)再判定。
|
||||
|
||||
## 目标选择策略规范
|
||||
接口:`ITargetSelector.SelectTarget(WeaponBase weapon, IEnumerable<EntityBase> candidates, float maxSqrRange)`
|
||||
|
||||
现有策略:
|
||||
- `NearestTargetSelector`
|
||||
- `HighestHealthTargetSelector`
|
||||
- `LowestHealthTargetSelector`
|
||||
|
||||
语义约定:
|
||||
- `HighestHealth` / `LowestHealth` 必须按“当前血量”筛选。
|
||||
- 当前实现读取 `HealthComponent.CurrentHealth`。
|
||||
|
||||
扩展策略步骤:
|
||||
1. 新建 selector 类并实现 `ITargetSelector`。
|
||||
2. 更新 `TargetSelectorType` 枚举。
|
||||
3. 在 `WeaponBase.CreateSelector` 中注册。
|
||||
4. 武器在 `OnWeaponShow` 或构造阶段选择策略。
|
||||
|
||||
## 攻击可视化效果规范
|
||||
接口:`IWeaponAttackEffect.Play(WeaponBase weapon, Vector3 position, EntityBase target, float radius)`
|
||||
|
||||
约定:
|
||||
- 可视化逻辑与伤害逻辑解耦。
|
||||
- 武器类只负责触发 `Play`,不把可视化细节塞回武器核心逻辑。
|
||||
- 当前阶段允许临时对象创建;后续若有性能压力再统一对象池化。
|
||||
|
||||
## 数据层规范(DRWeapon / WeaponData)
|
||||
`DRWeapon` 提供通用字段:
|
||||
- `Attack`、`Cooldown`、`AttackRange`、`AttackSoundId`
|
||||
- `Pramas`(字典,Key 建议统一转小写)
|
||||
- `Modifiers`
|
||||
|
||||
约定:
|
||||
- 参数解析尽量在数据层/初始化阶段完成。
|
||||
- 武器逻辑层读取 `WeaponData` 的强类型结果,不要散落 `Parse`。
|
||||
- 解析时必须容错:优先 `TryParse` + 默认值,避免运行时异常。
|
||||
|
||||
## 新增武器标准流程
|
||||
1. 定义枚举
|
||||
- 更新 `WeaponType`(保持递增值,避免重排已有值)。
|
||||
|
||||
2. 建立数据类
|
||||
- 新建 `WeaponXxxData : WeaponData`。
|
||||
- 如果有独有参数,提供强类型字段或统一初始化逻辑。
|
||||
|
||||
3. 建立行为类
|
||||
- 新建 `WeaponXxx : WeaponBase`。
|
||||
- 只实现差异化逻辑:`BuildStates`、`Check`、`Attack`、特有检测/动画。
|
||||
|
||||
4. 建立状态类
|
||||
- 推荐放在 `Weapon/WeaponXxx/` 目录,采用 partial 组织:
|
||||
- `WeaponXxx.cs`
|
||||
- `WeaponXxx.IdleState.cs`
|
||||
- `WeaponXxx.CheckOutRangeState.cs`
|
||||
- `WeaponXxx.CheckInRangeState.cs`
|
||||
- `WeaponXxx.AttackState.cs`
|
||||
|
||||
5. 建立可视化(可选)
|
||||
- 新建 `WeaponXxxAttackEffect : IWeaponAttackEffect`,在武器中组合调用。
|
||||
|
||||
6. 若为远程武器,建立子弹实体
|
||||
- `BulletXxx : Bullet`
|
||||
- `BulletXxxData : BulletData`
|
||||
- 通过武器赋予伤害/阵营参数。
|
||||
- 自动销毁应走对象池回收。
|
||||
|
||||
7. 接入实体展示与数据表
|
||||
- 确保 `DRWeapon` / `DREntity` 配置齐全。
|
||||
- `EntityExtension.ShowWeapon` 可正确映射到 `Entity.Weapon.WeaponXxx`。
|
||||
|
||||
8. 联动系统
|
||||
- 背包、商店购买/出售、UI 展示、事件流刷新。
|
||||
|
||||
## 代码检查清单(提交前)
|
||||
- 是否重复实现了 `WeaponBase` 已有通用逻辑。
|
||||
- 状态流转是否会卡死或漏转场。
|
||||
- 冷却计时是否在无目标时仍正常累积。
|
||||
- 目标失效(null/Unavailable/死亡)是否安全处理。
|
||||
- 命中检测是否符合武器设计(地面范围/射线/扇形)。
|
||||
- 数据参数是否全部容错解析。
|
||||
- 可视化是否与伤害逻辑解耦。
|
||||
- 是否正确订阅/解绑攻击属性(或复用基类方法)。
|
||||
|
||||
## 已知注意点
|
||||
- 目录中存在 `Pramas` 命名拼写历史包袱,保持兼容即可。
|
||||
- 文档中的“规范”优先级高于历史实现;历史实现若偏离,按本规范逐步收敛。
|
||||
Reference in New Issue
Block a user