本项目是一款基于 Unity 2022.3 的部落冲突类实时对战手游,采用客户端-服务器 TCP 长连接 + 帧同步(20 tick/s)架构,支持 45×45 战斗网格上的大规模单位对战。原始项目在 60 单位同屏战斗场景下存在严重性能瓶颈——单帧耗时峰值高达 54ms(仅 ~18 FPS),主因是 A* 寻路每帧 O(2401) 全量重置网格、热路径大量 LINQ/临时集合分配触发 GC 频繁抖动(单次 GC 暂停达 42ms)、寻路计算全部在主线程同步串行执行。
本人独立完成了从 Profiler 采样定位到全链路 DOTS 改造的完整性能优化:将 A* 寻路重构为 BurstCompile IJob 并行计算 + Grid Epoch O(1) 惰性重置,引入 64 槽 Scratch Pool 与预算型微批调度(每帧限 8 单位跨帧削峰),设计投射物双层对象池消除高频 Instantiate/Destroy,并将硬编码数据重构为 ScriptableObject 配置化。最终将战斗帧耗时从峰值 54ms 压降至 4.5ms(约 12 倍提升),峰值卡顿完全消除,稳定跑满 60 FPS。
1. A 寻路 Burst 化 + Grid Epoch O(1) 重置*
将托管 class Cell[]重构为blittable BurstNodeData struct+扁平索引NativeArray完整重写 A* 搜索为[BurstCompile]IJob(~260行),支持 Burst 编译执行。引入 SearchId+Epoch 递增机制,首次访问格子时 O(1) 惰性初始化替代每帧 O(2401) 全量 Reset。构建双套blocked数组(有/无障碍模式)供实时查询。
2. 预算型微批寻路调度
核心洞察:战斗大部分帧几乎无寻路,偶发 10~20 单位集中重寻路制造峰值。设计跨帧持久队列 + MAX_PATH_UNITS_PER_FRAME=8 预算上限,每帧只处理8个单位的寻路请求,剩余自然延至下帧。将 RouteB全量批处理的22ms峰值进一步削至4.5ms,消除所有突兀卡顿。(全链路从初始 54ms 降至 4.5ms)
3. 64槽Scratch Pool + 批量Job调度
设计三阶段流水线(Queue→Schedule→Read):先收集所有 A* 请求占槽位,再统一 JobHandle.CombineDependencies().Complete() 一次等待全部 Job,最后批量读取结果。热路径全面移除LINQ与临时集合分配,复用Battle级sortedTargetBuffer等预分配 buffer。
4. 投射物双层对象池
模拟层ProjectilePool(纯 C#,128 槽数组),表现层MonoPool
(按 prefab 分 Stack)。3处new Projectile() 改为 RentProjectile(),命中后 ReturnProjectile() 归还。消除每场数百~数千次堆分配与Instantiate/Destroy开销。
5.ScriptableObject 配置化
将Data.cs硬编码数据重构为ScriptableObject 双源配置(代码默认值 + 资源覆写),支持 Excel 导入,策划可脱离代码调参,服务器协议兼容的枚举顺序保持不变。
6.ECS 战斗子世界
搭建独立BattleSimulationWorld,创建BattleEcsRuntime生命周期管理器,注册ProjectileTimerSystem接管投射物倒计时。通过BattleEcsFrameState单例组件实现托管侧→ECS 侧数据同步,与原有 List 完全解耦,3 行代码集成(Initialize/Update/Dispose)。
GitHub仓库: https://github.com/primer496/COClike