把 RTS 放进浏览器后,最容易得到的结论是"脚本慢"或"draw call 太多"。但当实例化、批量提交已经加入,游戏仍然卡顿时,这些判断就太粗了。
在《铁幕前线:新港战区》的 EVEngine WebGPU 实践中,我们把 500 单位压力场景拆到查询、表现、战斗、弹体和逻辑补帧,再做前后对照。这篇记录其中一轮优化:它改善了帧率,也清楚地暴露了尚未解决的预算缺口。
先把"500 单位"说清楚
单位数量一样,工作量也可以完全不同。全选、悬停敌人、补给车维修、移动攻击,会触发不同的数据查询与表现路径。普通对局中单位不断死亡,和为了维持负载而使用高生命值的合成战斗,也不是同一项基准。
本文数据来自 2026 年 11 月 1 日"热路径第二轮"的本地记录:Edge、AMD RDNA4 硬件 WebGPU;四类场景,每个版本各采样 180 帧,正序和反序各一轮,共 2880 帧。每组剔除最初三帧,并对齐共同模拟 tick 窗口。压力夹具使用高生命值维持兵力,不能把结果当作普通对局的帧率保证。
CPU 帧耗时来自 Browser::frame,FPS 按平均帧间隔求倒数。它们不是 GPU timestamp。四组两轮共检查 671 个共同采样 tick 的阵营、单位、弹体等指定计数一致,这能保护一部分行为语义,但不能替代完整世界状态比较。
第一个热点,是重复取得同一批数据
模型、音效、迷雾、小地图都需要知道可见单位的状态。如果每个系统各自从原生层读取一次,跨语言边界就会重复构造数组、脚本表和字符串字段。
问题不只在单次查询的算法复杂度,还在同一帧重复付费。一次调用很小,乘上系统数、单位数和帧数,就可能占据可观的 CPU 时间。
这轮改动让几个表现消费者复用本渲染帧按需取得的可见单位行;开火与命中特效对同一 tick 的相同来源、目标复用点查询结果。缓存有明确的有效期,模拟决策仍读取原生权威状态。
移动攻击场景中,单位查询约从每帧 187 次降到 92 次,对应作用域从 8.35 ms 降到 5.20 ms。这里减少的是重复查询和数据搬运,不是停止更新世界状态。
批量 setter 之后,还要看计算在哪里
把一千次提交合成一个调用,很容易在接口上看到收益。但如果一千个矩阵、屏幕投影和临时数组仍在脚本循环里计算,主要成本可能还在。
这轮把载具关节矩阵合成、世界姿态和枪口坐标计算移到原生层级批处理。脚本负责提供少量局部参数,原生按层级整理计算与提交。
移动攻击场景的载具姿态作用域从 5.57 ms 降到 3.12 ms 每帧。与此同时,步兵虽然增加了静止快速路径,主循环依然在脚本里,其更新作用域只从 6.11 ms 降到 5.59 ms。两条路径的结果提醒我们:接口批量化与计算批量化,是两项需要分别验证的工作。
每个 tick 重建索引,可能吃掉降频的收益
自动索敌降频之后,战斗系统仍可能每个逻辑 tick 遍历单位、整理目标状态并排序。查询次数下降,不代表查询之前的准备工作也下降了。
这轮在成员和 generation 合格的身份不变时,复用名称与句柄排序排列;只在群体密度判断确实需要时建立 X 索引。目标的当前状态和 Sensing 仍按原规则更新,避免把过期状态误当作加速成果。
但测量结果相当克制:移动攻击组战斗系统每 tick 从 3.05 ms 降到 2.96 ms,改善很小。排序复用处理了一部分成本,组件访问和目标状态整理还在。优化方案看起来合理,仍要允许数据告诉我们它不是主要解法。
弹体系统更适合从数据结构和访问范围入手
旧路径每 tick 把弹体旧状态复制到新的 map,固定落点命中时还会遍历全场寻找受击者。弹体多、单位多时,这两项工作相互放大。
修改后,旧状态使用连续的 key 和位置行;固定落点和溅射复用按需建立的邻域索引,同时保留原有 ECS 结算顺序。
移动攻击组的弹体作用域从 1.76 ms 降到 0.68 ms 每 tick。相比单纯减少函数调用,这种改动直接减少了复制和无关对象访问。不过,结算顺序、同 tick 死亡和溅射边界都必须回归,否则性能提升可能来自改变玩法。
为什么每帧变快,不能全部算成算法加速
固定时间步模拟需要追赶经过的时间。当一帧很慢,下一帧可能执行多个逻辑 tick;每个 tick 又继续占用时间,形成补帧压力。
因此,同一个系统既要报告每帧成本,也要报告每 tick 成本。战斗系统每帧从 9.84 ms 降到 7.70 ms,看起来改善明显,但每 tick 只有 3.05 → 2.96 ms;其余变化还包含单帧补 tick 数减少的反馈。
父子作用域也不能相加。表现更新已经包含其中的单位循环,再把两项相加,会把同一段时间算两遍。脚本 scope 的 self 时间还可能包含没有独立打点的原生调用,不能直接叫作"纯脚本执行时间"。
整帧确实改善,但离目标仍远
同一轮对照中,全选场景从 17.55 提升到 19.35 FPS,悬停敌人从 15.85 到 18.46 FPS,多补给车从 13.56 到 15.63 FPS,移动攻击从 9.09 到 11.50 FPS。
移动攻击组优化后,Crowd 仍约 14 ms 每帧,表现更新约 23 ms,步兵脚本约 5.6 ms。60 FPS 的整帧预算只有约 16.7 ms,这些结果显然还没有达标。
这轮有 11 项聚焦 C++ 契约及原生生产、建造阻挡、运输循环等验证,不能据此声称全仓库检查通过。后续真实试玩还反馈了移动鬼影与建筑闪烁,相关聊天仍在诊断深度历史和动态遮挡时序。没有脚本异常或 WebGPU 报错,也不能证明视觉已经正确。
这次实践更值得复用的方法是:固定负载、拆开查询与计算、核对缓存生命周期,保留失败和小收益,再检查整帧是否真正改善。优化工作的终点是游戏体验与预算达标,而不是代码里出现了多少个 batch。
数据依据:铁幕前线 2026 年 11 月 1 日热路径第二轮本地验证记录。指定硬件与压力夹具的结果不代表当前线上版本性能;后续渲染问题仍需继续验证。500 单位 RTS 为什么还没到 60 FPS:一次 WebGPU 游戏性能诊断