Unity 大型 RTS 一个月帧数翻 3 倍:先查 profiler,再谈重构

开发者 Alejandro Nunez 自述用一个月把 Unity ECS 与 DOTS 大型 RTS The Last General 的帧数提高了 3 倍。该数字为自述,但方法对照 Unity 文档站得住:重新分批减少约 90% 批次,块占用率接近每块 128 个实体,任务调度也做了重排。

Unity 大型 RTS 一个月帧数翻 3 倍:先查 profiler,再谈重构
本篇导航11 个章节

一位开发者自述,他用一个月把自己大型 Unity RTS 的帧数提高了 3 倍。这个数字是开发者自述,不是本站可复现的实测基准,但其方法值得拆解:他先用剖析工具找瓶颈,再改代码。本篇拆解他做了什么、Unity 官方文档能印证什么、以及哪些内容仍未核实。

先剖析,再重构。自制说明卡,不是游戏截图。

一眼看懂

  • 自述口径:开发者 Alejandro Nunez 称,他在一个月内把大型 RTS The Last General 的帧数提高了 3 倍,该游戏用 Unity ECS 与 DOTS 制作。

  • 方法:先用剖析工具找出最严重的问题,而不是一上来就重构。

  • 自述最大收益:重新分批后批次减少约 90%,同时减轻 CPU 分发与 GPU 命令负担。

  • 本站未核实:来源未公布改动前后帧数、硬件与工程代码,因此本篇不作可验证的性能断言。

先把说法讲清楚

2025 年 9 月 12 日,80.lv 报道了开发者 Alejandro Nunez 优化其大型即时战略游戏 The Last General 的自述。标题数字是一个月内帧数提高到原来的 3 倍。请按其本来面目理解这个数字:经

80.lv 转述的开发者自述。来源文章没有公布帧数、测试场景、硬件规格与工程代码,因此这里没有任何可独立复现的内容,本篇也不会编造这些细节。

来源确实给出了可用的方法与一串具体改动,每一项都可以对照 Unity 官方文档核查其合理性。正是这个区分决定了全文的写法:结果数字未核实,但技术本身是真实、有文档的 Unity 概念,开发者对每一项的 reasoning 都可以单独审视。

第一步:先剖析,再谈重构

Nunez 的起点是剖析工具,而不是重写。他用剖析找出最严重的问题与瓶颈,据称同时减轻了 CPU 与 GPU 负担。这个顺序很关键,Unity 自家的 DOTS 指引说的也是同一件事:用基于 ECS 的代码开发时,应始终开着 CPU Profiler 并留意控制台,因为 Profiler 会告诉你写出的系统是否可能引发性能问题。

针对 ECS 工程,Unity 文档列出两个 Entities Profiler 模块:Entities Structural Changes(显示框架何时创建或销毁实体与组件)与 Entities Memory(显示每帧各原型内存占用)。结构变更天生昂贵,因为框架会把实体及其全部数据完整复制到另一个原型。因此,任何在运行时大量创建、销毁或重配实体的 RTS,都应预期结构 churn 先出现在剖析结果里,而不是别处。

最大收益:把本应同批的实体重新分批

Nunez 称重新分批是他最大的收益之一。Entities Graphics 不会把非同一时间实例化的实体合并到同一批次,于是本应一起渲染的实体会被拆成许多小批次。据他自述,重新分批后批次减少约 90%,CPU 收益来自不再分发数千个批次,GPU 收益来自待执行命令大幅减少。

Unity 的 Entities Graphics 文档支撑这一机制本身:它把编写期 GameObject 烘焙为实体并生成 BatchRendererGroup 批次,每个绘制命令渲染一组共享同一网格与材质的实例。因此批次越少,CPU 与 GPU 交界两侧的每批准备工作就越少。这是渲染器的文档化属性,并不依赖 Nunez 的数字。

修复本身有两种做法,区分很实际:要么同一时间实例化全部实体,要么把一组实体的 EntitiesGraphicsChunkInfo 组件重置为默认值,让 Entities Graphics 为这些实体重新计算批次。若选第二种,Nunez 提醒,必须在同一帧内对目标批次的全部实体执行。他的例子是:写一个系统一次性抓取所有应同批的小行星并全部切为默认 EntitiesGraphicsChunkInfo,然后看着批次数量骤降。

他的验证建议同样具体:用 RenderDoc 查看哪些物体被无故放进独立小批次,从而知道哪些需要这一招。这是任何读者都能在自己工程里复现的诊断步骤,也是防止盲目套用这一招的正确解药:只对 RenderDoc 实际显示为碎片化的组做重新分批。

开发者自述批次减少约 90%。自制说明卡,不是游戏截图。

块占用率:让每块接近 128 个实体

第二项收益是把块占用率提升到接近每块 128 个实体。在 ECS 里,共享同一原型的实体一起存放在 16 KiB 的块中,Unity 现行 Entities 文档规定每块上限为 128 个实体,实际容量由组件大小决定。远低于容量的块会在近乎空置的存储上浪费内存带宽,因此占用率是一个真实、可测量的量,在 Unity 的 Archetypes 窗口中与块容量、未用空间并列显示。

Nunez 用的一项做法是把实体拆为物理与逻辑实体和独立的渲染实体。直接收益是占用率更好,但拆分还带来第二项收益:远处实体的渲染可以完全关闭,同时其碰撞体与其他逻辑保持激活。这个分离本身就是值得借鉴的要点,哪怕读者的块数量不同:让必须持续模拟的数据,与只在可见时才重要的数据分开。

这里需要一句版本说明。较旧的 Unity 文档示例曾为小型原型算出高于 128 的块容量,因为 128 上限是较新 Entities 版本才有的。读者因此应以自己所用 Entities 版本报告的块容量为准,而不是把 128 当作所有版本通用的常量。开发者的方向(让块更满)不受这句说明影响,但确切上限取决于所用版本。

开发者自述块占用率接近每块 128 个实体。自制说明卡,不是游戏截图。

任务与系统:重排、断依赖、别再并行化小任务

其余自述收益都关于调度,而非渲染。Nunez 重排了系统、打断了任务之间以及系统之间的读写依赖,并取消了短任务的并行化。每一项都是可辨认的 ECS 权衡,而非魔法开关。依赖链会迫使工作等待,打断它才能让任务重叠;但把几乎立刻跑完的任务并行化,调度开销可能超过执行节省,因此短任务单线程跑在实践中反而更快。

重排系统、打断依赖、停止并行化短任务。自制说明卡,不是游戏截图。

文本与层级:两项会复利的小收益

还有两项改动补齐了清单。世界空间文本 GameObject 被替换为 Latios Calligraphics 文本,把基于 GameObject 的文本对象从一个 otherwise 以实体搭建的场景中移除;子实体数量减少,降低了 CalculateHierarchyLocalToWorld 任务耗时,即沿层级重算世界变换的工作。单看每一项都不 dramatic,但与分批、块占用工作叠加后,它们消除的是随实体数量增长的每帧开销,而这正是 RTS 最怕的成本类型。

世界空间文本 GameObject 替换为 Latios Calligraphics 文本。自制说明卡,不是游戏截图。
子实体更少,CalculateHierarchyLocalToWorld 工作更少。自制说明卡,不是游戏截图。

物理思路:建议,而非已宣称的收益

最后,来源以较弱的语气列出物理思路,本篇保留这个语气。合并静态碰撞体、使用增量静态 broadphase 功能可能有助于性能,网格休眠系统(当特定格子内及周围无物移动时把物体转为静态)也是如此。来源的措辞是可能有帮助,而非已经有帮助,因此读者应把这些当作下一步可剖析的实验,而不是本案例的实测结果。

合并碰撞体、增量静态 broadphase 与网格休眠是待验证的建议,不是实测收益。自制说明卡,不是游戏截图。

开发者清单:本案例值得带走的东西

  • 先剖析。改任何东西之前先打开 Profiler 与 Entities 模块,按实测开销给瓶颈排序。

  • 用 RenderDoc 检查批次碎片化。若应同批的物体落在独立小批次里,就在同一帧内重新分批。

  • 留意 Archetypes 窗口中的块占用率。占用率差时,把模拟数据与纯渲染数据拆开。

  • 审查任务依赖与短任务。打断让工作串行化的依赖链,别为几乎立刻跑完的任务支付调度开销。

  • 削减随数量增长的单实体开销:子实体、层级变换、实体场景中的 GameObject 文本。

  • 每改一处就重新剖析。帮了一个工程的技巧可能害了另一个工程,只有剖析结果能告诉你自己属于哪种。

剖析、分批、块、任务,然后在发布前用 RenderDoc 验证。自制说明卡,不是游戏截图。

证据边界:本篇不主张什么

本篇不主张经核实的 3 倍帧数提升,因为来源未公布帧数、硬件、测试场景或代码。本篇不展示任何代码,因为来源未公布可验证的工程代码;上述技术描述是经对照 Unity 文档核查合理性的开发者自述步骤,不是本站执行过的代码。本篇不把物理思路当作结果,因为来源本身也只把它们列为可能性。本篇不把任何图片冒充为游戏截图或剖析截图:全部 8 张图均为自制说明卡,每张图注都如实标注。

来源

  • 80.lv《Developer Explains How He Tripled Performance of Unity Game》,2025 年 9 月 12 日:开发者自述、全部技术描述与约 90% 批次数字的来源。

  • Unity Entities 文档,Entities Profiler modules 与 Entities Structural Changes:剖析模块与结构变更开销。

  • Unity DOTS Best Practices,Implementation fundamentals:始终剖析、始终开着 CPU Profiler、留意控制台。

  • Unity Entities Graphics 文档,Entities Graphics Performance:BatchRendererGroup 批次、每绘制命令共享网格与材质。

  • Unity Entities 文档,Manage chunk allocations:16 KiB 块、现行 Entities 版本每块上限 128 个实体。

  • 一个缺失字形就要 16 MB:Foxy Dumplings 如何把字体图集内存从 48 MB 压到 4-8 MB

  • 一行被重算 63000 次的字符串长度,是怎么让 GTA Online 读盘 6 分钟的

收藏这篇攻略

登录后可收藏攻略,并在不同设备同步。

登录 / 注册