145 lines
5.6 KiB
Markdown
145 lines
5.6 KiB
Markdown
# CodeX TODO
|
||
|
||
## GPU Instancing 改造路线
|
||
|
||
### 目标定义
|
||
|
||
- `SimulationWorld` 继续作为敌人 `position / rotation / state` 的唯一真相源。
|
||
- 新增 `InstanceRendererComponent` 作为 Presentation 侧批量渲染组件,不把批次构建和 GPU Buffer 管理塞回 `SimulationWorld`。
|
||
- 先做 `Graphics.DrawMeshInstanced` 低风险版,确认链路跑通后,再决定是否升级到 `DrawMeshInstancedIndirect`。
|
||
- P3 首阶段只处理“敌人批量渲染”,不同时扩大到投射物、掉落物和所有特效。
|
||
|
||
### 架构边界
|
||
|
||
- `SimulationWorld`
|
||
- 只负责逻辑 Tick、生命周期同步、状态容器与碰撞结算。
|
||
- 不负责 `Mesh / Material / MaterialPropertyBlock / ComputeBuffer`。
|
||
- `InstanceRendererComponent`
|
||
- 只负责收集可渲染实例、按 `Mesh + Material + Shadow + Layer + RenderState` 分组、构建 batch、发起 draw call。
|
||
- 只消费 `SimulationWorld` 输出,不反写 sim 状态。
|
||
- `TransformSync`
|
||
- P3 第一阶段继续保留,用于 HPBar、受击特效、挂点和现有表现依赖。
|
||
- 不要求一开始就把所有敌人 `Transform` 写回移除,否则风险过高。
|
||
- 敌人 GameObject
|
||
- 第一阶段继续保留,用于碰撞、生命周期、事件桥和表现挂点。
|
||
- 仅逐步移除“每敌人独立 MeshRenderer”这条渲染路径。
|
||
|
||
### 组件规划
|
||
|
||
1. 新增批量渲染组件骨架
|
||
- 建议文件:
|
||
- `Assets/GameMain/Scripts/CustomComponent/InstanceRendering/InstanceRendererComponent.cs`
|
||
- `Assets/GameMain/Scripts/CustomComponent/InstanceRendering/EnemyInstanceRegistry.cs`
|
||
- `Assets/GameMain/Scripts/CustomComponent/InstanceRendering/EnemyInstanceBatch.cs`
|
||
- 建议职责:
|
||
- `InstanceRendererComponent`:帧级调度、统一提交 draw call。
|
||
- `EnemyInstanceRegistry`:维护 `EntityId -> RenderBinding`,缓存 mesh/material/archetype。
|
||
- `EnemyInstanceBatch`:缓存每组矩阵、颜色、闪白参数和批次拆分结果。
|
||
|
||
2. 接入 `GameEntry`
|
||
- 文件:`Assets/GameMain/Scripts/Base/GameEntry.Custom.cs`
|
||
- 处理:
|
||
- 增加 `GameEntry.InstanceRenderer`
|
||
- 与 `SimulationWorld` 一样在启动时自动获取或挂载组件
|
||
|
||
### 第一阶段:低风险版 `DrawMeshInstanced`
|
||
|
||
1. 建立渲染注册表
|
||
- 注册时机:敌人 show 时缓存渲染资源引用,hide 时释放注册。
|
||
- 注册内容:
|
||
- `EntityId`
|
||
- `Mesh`
|
||
- `Material`
|
||
- 阴影/Layer/子类型信息
|
||
- 受击闪白、稀有度色等实例化属性默认值
|
||
- 约束:
|
||
- 注册表只缓存渲染资源和 archetype,不缓存位置真相数据。
|
||
|
||
2. 从 `SimulationWorld` 读取实例数据
|
||
- 读取来源:`_enemies` 或对外只读查询接口。
|
||
- 每帧收集:
|
||
- `Matrix4x4`
|
||
- 朝向/缩放
|
||
- `flashAmount`
|
||
- `baseColor`
|
||
- 其他实例化参数
|
||
- 约束:
|
||
- 由 sim 输出生成当前帧渲染数据,不从敌人 `Transform` 反推逻辑状态。
|
||
|
||
3. 按批次分组并提交
|
||
- 分组键至少包含:
|
||
- `Mesh`
|
||
- `Material`
|
||
- `ShadowCastingMode`
|
||
- `ReceiveShadows`
|
||
- `Layer`
|
||
- 需要的渲染状态位
|
||
- 提交方式:
|
||
- 每批最多 `1023` 实例
|
||
- 使用 `Graphics.DrawMeshInstanced`
|
||
- 通过 `MaterialPropertyBlock` 下发实例颜色和闪白参数
|
||
|
||
4. 接入现有 Instanced Shader
|
||
- 文件:`Assets/GameMain/Materials/Shaders/SimpleInstancedFlash.shader`
|
||
- 处理:
|
||
- 复用现有 `_BaseColor / _FlashColor / _FlashAmount` 实例化属性
|
||
- 确认敌人材质启用 instancing
|
||
- 不在第一阶段同时改复杂动画或多 Pass 材质
|
||
|
||
5. 替换敌人独立 Renderer 路径
|
||
- 第一阶段做法:
|
||
- 保留敌人实体和挂点
|
||
- 禁用敌人身上的 `MeshRenderer/SkinnedMeshRenderer`
|
||
- 改由 `InstanceRendererComponent` 统一绘制
|
||
- 约束:
|
||
- 碰撞、伤害、掉落、状态切换仍完全走现有逻辑链路
|
||
|
||
### 第二阶段:高上限版 `DrawMeshInstancedIndirect`
|
||
|
||
1. 升级批次数据结构
|
||
- 将 `Matrix4x4[]` 和实例属性数组迁移到 `ComputeBuffer` / `GraphicsBuffer`
|
||
- 建立按 archetype 持久复用的 buffer,避免每帧重建
|
||
|
||
2. 升级提交方式
|
||
- 使用 `Graphics.DrawMeshInstancedIndirect`
|
||
- 为实例数量、剔除结果和参数下发建立独立 buffer
|
||
|
||
3. 逐步加入可选优化
|
||
- 视锥剔除
|
||
- 距离分层
|
||
- LOD
|
||
- 大规模敌人下的批次复用和 buffer 容量管理
|
||
|
||
4. 进入该阶段的前提
|
||
- `DrawMeshInstanced` 版本已验证视觉正确
|
||
- `5k` 规模下 draw call 或主线程提交成本仍是瓶颈
|
||
- 否则不要过早把复杂度拉到 `Indirect`
|
||
|
||
### 风险控制
|
||
|
||
- 不要把 GPU batch 容器放进 `SimulationWorld` 主状态里。
|
||
- 不要让碰撞、索引或目标选择依赖 `InstanceRendererComponent`。
|
||
- 不要一上来就移除 `TransformSync`,先保住现有 HPBar/特效/挂点行为。
|
||
- 不要在第一阶段同时处理敌人、投射物、掉落物三类 instancing。
|
||
|
||
### 验证口径
|
||
|
||
1. 功能回归
|
||
- 敌人朝向、受击闪白、死亡隐藏、精英/普通配色与当前一致
|
||
- `Battle -> LevelUp -> Shop -> Battle` 循环不丢渲染实例
|
||
|
||
2. Profiling 指标
|
||
- `0.5k / 1k / 1.5k / 2k / 5k` 敌人
|
||
- `Draw Calls`
|
||
- `SetPass Calls`
|
||
- `Main Thread`
|
||
- Render Thread / GPU 时间
|
||
|
||
3. 阶段验收
|
||
- 第一阶段验收:
|
||
- 先证明 `DrawMeshInstanced` 跑通且视觉一致
|
||
- Draw Calls 相比当前路径明显下降
|
||
- 第二阶段验收:
|
||
- `5k` 敌人规模下主线程提交和渲染耗时继续下降
|
||
- buffer 生命周期稳定,无泄漏、无错绘、无实例残留
|