关于 scenario-unreal-performance
面向 Unreal Engine 5.8 项目性能工程的技能,指导工程师测量、诊断并验证性能问题。以阶段毫秒数、可重复的同路线捕获和独立卡顿分析为核心。
主要功能
- 01按游戏线程、渲染线程和 GPU 分类瓶颈
- 02规划基准捕获并分析 Trace
- 03测量配置与渲染功能的性能变化
- 04审计关卡和资产设置
- 05单独诊断卡顿并验证修复
适用场景
- 01定位目标硬件上的帧时间瓶颈
- 02比较 Lumen、Nanite 或 VSM 的性能成本
- 03排查关卡加载、GC 与生成造成的卡顿
- 04用重复测试证明性能修复效果
MCP 相关
该技能要求使用 scenario-unreal-expert 的通道执行命令,并提及可通过 MCP 使用工作流。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-unreal-performance安装后在 Claude Code 中输入/scenario-unreal-performance确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/ue_perf.py详细介绍
Unreal Engine 5.8 性能工程
这里所说的专家级,关注的是每个阶段耗费的毫秒数,而不是每秒帧数:通过一次真实可靠的捕获来判断瓶颈;根据实际执行工作的线程(而不是处于等待状态的线程)解释最糟糕的帧;按测得的影响大小排序修复;并在相同路线和构建版本上重复运行,以证明结果,同时将卡顿与平均值分开评估。性能工程师负责测量、诊断和验证;大多数修复工作则交给负责相关内容的队友。如果这里提到的同名技能不在你可用的技能中,请让用户安装它
(npx skills add scenario-labs/skills --skill <name>);如果无人值守,请根据工具架构继续操作,并标明这一缺口。
必备背景: scenario-unreal-expert(通道、审核流程、5.8 陷阱)。
状态(2026-09-24): scripts/ue_perf.py 尚未在 Unreal 中运行;其纯逻辑层已通过 tests/code/unreal-performance/run_all.sh(使用合成捕获的 50 项离线测试)。所有 UE 名称均标记为 [verify];首次运行:job_probe_perf.py(流程 P0)。
立场(专家经验差异)
- 按阶段衡量毫秒数,再选对工具。 在 60 fps 下,游戏线程、渲染线程和 GPU 各有 16.6 ms,流水线分别处理游戏帧 N、渲染帧 N-1、GPU 帧 N-2(W4R [00:05:17] [00:08:26])。报告毫秒数,绝不报告 fps(ARI22 [00:14:44])。
stat unit用于分类,Insights 用于定位 CPU 上的具体开销,GPU 捕获用于解释 GPU 开销;当插桩信息不足时,采样分析器可以说明原因(KEN [00:04:04];NORSE [00:17:30])。 - 修复前先做真实的性能捕获。 在目标硬件上运行 Cooked Test 或 Development 构建,并固定路线;锁定动态分辨率(75%),仅在归因各个渲染阶段时关闭异步计算,证明性能时不要这样做(NORSE [00:44:40] [00:45:12])。对于“是否符合预算”,使用精简捕获;对于“为什么”,使用详细捕获(
-statnamedevents,开销约 20%)(NORSE [00:11:27]);-NoVerifyGC和-handleensurepercent=0可排除 Development 构建中虚假的卡顿(NORSE [00:13:35] [00:16:23])。 - 最长的条形往往代表等待,而等待也占预算。 排除空闲、等待和帧同步标记,并沿依赖关系追踪到实际工作的线程;帧 N 的渲染帧过慢,会表现为帧 N+1 中游戏线程等待(KEN [00:09:54] [00:16:30])。等待动画和移动最终处理的开销(300 个 NPC 时约 2 ms)可以回收(W4R [00:16:20])。
- Epic 的可扩展性设置面向 30 fps 模式。 High(2)才是 60 fps 级别,除非自行构建,否则不会选择 60 fps 设备配置文件(OZ26 [00:11:00] [00:16:50];LVP)。分辨率链路(dynres 从 800p 到 1080p,TSR 升至 1440p,空间升采样至 4K)是最大的单项渲染调节手段(OZ26 [00:14:41];W4R [00:43:08])。
- 为每项功能设定预算,按差值衡量,并沿着调用树追踪。 在 60 fps 下,Lumen GI 加反射约耗时 4 ms,应通过关闭 Lumen 后的帧时间差来衡量(OZ24 [00:37:55])。对于 Nanite,先设定预算,再查看 Evaluate WPO 和 Pixel Programmable 视图,最后查看 Overdraw;视图可以定位问题,但不能证明问题(OZ24 [00:29:18] [00:32:13])。对于 VSM,追查静态和动态失效中开销较大的一项(OZ24 [00:48:59])。异步计算应针对每项功能进行 A/B 测试:在 Witcher 演示中总体约节省 1.5 ms,但将 Lumen 反射切回图形管线带来的收益更大(W4R [00:20:42] [00:21:48])。
- 默认设置注重易用性,最大收益来自内容设置。 到处使用复杂碰撞、加载时执行重叠检测、在完整输出分辨率下使用 After DOF 半透明、在 VSM 旁使用 DF 阴影、让 PDO 或 WPO 植被重复付出三次开销(VisBuffer、VSM、自定义深度)、局部阴影灯光互相重叠、道具仍设为 Movable(NORSE [00:38:53] [00:49:03] [00:53:48] [00:49:35];FFW [00:52:59];ARG [00:11:54])。
- 卡顿需要单独处理。 数百毫秒的卡顿几乎可以确定是阻塞式加载,应在创作阶段通过验证器拦截;GC 开销取决于 UObject 数量;生成不是增量式的;摄像机切换会丢失遮挡历史;主机平台不会在运行时发生 PSO 卡顿,PC 和 Mac 则会在冷启动状态下测试(HITCH [00:43:07] [00:45:16] [00:38:31] [00:25:08] [00:35:50];W4R [00:44:44];PSO blog)。动态分辨率无法解决卡顿(W4R [00:43:38])。
- 先修复内容,再用临时补救措施。 异步物理初始化、增量式 GC 和 dynres 会掩盖问题的增长(HITCH [00:22:56] [00:41:56]);应限制出现峰值的单项功能,而不是让 dynres 降低整帧的画质(W4R [00:38:55])。
优先确认
| 输入项 | 影响 | 未提供时的默认值 |
|---|---|---|
| 目标硬件及谁在其上进行采集 | 所有数据;这台 Mac 无法部署到开发套件(平台 SDK 和源代码构建、PKG) | 先询问;同时将 Mac 数据标记为替代数据 |
| 帧率目标、输出分辨率 | 阶段预算、分辨率链 | 60 fps;主机上的输出分辨率为 4K |
| 动态分辨率策略 | 性能分析期间锁定;发布时的范围 | 开启,设为次级 1440p 的 55% 至 75%(OZ26 [00:15:48]) |
| 可用构建版本 | Test 中的验证;内存跟踪需要 Development(INS);Launcher 引擎只会打包 DebugGame、Development、Shipping(PKG) | 使用源代码引擎的 Test,否则使用带噪声标志的 Development |
| 路线 | 可重复性 | 最繁忙的场景、人群、战斗、最高移动速度、镜头切换,作为 BugIt 航点 |
| 质量标准、由谁决定取舍 | 一致性门槛 | 外观负责人(灯光、美术) |
工作流
import ue_perf as P(Agent 端)。命令通过 scenario-unreal-expert 的通道执行;打包版本只接受启动标志和 Level Sequence 事件轨道。
- 探测工具。 使用
job_probe_perf.py查询 API 名称和 cvar;对第一个 TraceQuery 输出调用P.schema_probe(jsonl)。GATE:每个计划使用的 cvar 都打印出了值;TraceQuery 的键均已映射。 - 明确差距,设定预算。 38 fps 对应 26.3 ms,比 16.67 多 9.6 ms。
P.budget_table(platform, fps, pass_budgets)(OZ26 [00:45:55])。GATE:每一行都有来源,各阶段的通道预算合计不超限。 - 确定路径并进行真实采集。 使用
P.route_from_bugit(log)(打包时使用P.route_event_track),P.capture_plan("budget", ...),运行三次。GATE:三次精简运行,已知性能波动,且采集规范一致。 - 分类。
P.diagnose_bound(frames, 16.67, context=...)会给出瓶颈、差距、注意事项和下一次采集方案;读取可扩展性设置(P.stat_sequence("scalability_readback"))。GATE:已标明瓶颈,差距以 ms 为单位,且已解答注意事项。 - 优先调整配置,每次测量只改一项。 设置 Scalability 2,并添加一个用于激活它的选择器;分辨率链(
P.day_one_60fps_cvars、P.device_profile_block、P.write_ini_section,先备份);通过P.apply_ini_keys应用P.day_one_engine_ini()(将 Use Simple 设为 Complex,流送期间将 NeverUpdate 用于重叠检测);将 Lumen foliage threshold 设为 0,并将 roughness threshold 设为低于 0.4(从 Performance Overview 读取)(OZ26 [00:41:56]);在 Gen9 上设置r.GTSyncType 2;将流送控制在默认的 5 ms 以内。在P.ChangeLog中记录每项改动。GATE:回读的 LastSetBy 为 DeviceProfile;每项改动都经过测量;画质取舍经过 A/B 测试。 - 针对瓶颈进行深入分析(步骤 P6 到 P7b)。 GPU:将归因后的
ProfileGPU数据导入P.gpu_pass_table、P.lumen_delta,然后通过P.feature_budget_check(RT 场景)、P.nanite_triage和P.vsm_triage分析数据;通过P.ab_plan(P.ASYNC_AB_VARIANTS)和P.ab_verdict分析异步计算。 游戏线程:将 TraceQuery 数据导入P.analyze_trace(非等待计时器、与屏幕数据对比的计数、game_wait、advice),并分析P.spawn_bursts、按组分类的dumpticks、obj list -countsort。 流送:在 World Partition Insights 中查看每个单元格的开销;在最高速度遍历中测量从请求到可见的延迟;仅将P.STREAMING_AB_VARIANTS用于 A/B 测试。GATE:每个超预算类别都有明确的原因、资产和负责人。 - 审计并分派修复任务。 使用
P.perf_audit_level()、P.perf_audit_assets()(移动性、碰撞来源、WPO 边界、Displacement Fade),通过P.change_requests(rows)将请求分派给负责人;达成一致后再应用。使用相同的 BugItGo 视图检查一致性(P.parity_pair)。GATE:所有needs_eyes对都经过目视判断。 - 卡顿分析。 先冷启动再热启动执行
capture_plan("hitch")(冷启动仅在非控制台平台上);使用P.hitch_snapshots(dir),并将每个快照交给P.analyze_trace;对路径中的剪切点使用P.camera_cut_spikes;将未分类的帧交给采样分析器。GATE:冷启动路径没有快照,游戏过程中没有阻塞加载,GC 事件低于 2 ms,UObject 数量低于 500k。 - 验证并设防。 使用相同的路径、构建版本和设备;每项运行三次;采用选定的异步计算方案;锁定 DRS,并保持出货时的设置。使用
P.compare_runs,然后使用P.write_proof_report。通过 Horde 中按趋势跟踪的每夜自动化性能测试进行设防(OZ26 [00:47:43])。GATE:结论为stable_at_target,并填写“not tested”。
数值
| 项目 | 数值 | 相对于、来源 |
|---|---|---|
| 阶段预算 | 每阶段 16.67 ms(30 帧时为 33.3) | 游戏、渲染、GPU、W4R [00:05:17] |
| Lumen GI 和反射 | 60 帧时约 4 ms,30 帧时约 8 ms | 帧间隔,控制台 High,OZ24 [00:37:55];LVP |
| 粗糙度阈值 | 默认 0.4,内容接近 0.35;0.4 相较于无阈值快 3 倍,且难以察觉 | OZ26 [00:41:56];W4R [00:33:42] |
| HWRT 场景 | 活跃实例少于约 100,000 个(主机平台,LVP);Witcher:近场约 150 m,RT 池约 400 MB,异步更新耗时 0.5 ms,每帧动态三角形约 40,000 个 | PS5,W4R [00:29:30] [00:30:37] |
| 异步计算 | 总体节省约 1.5 ms;反射在图形处理中更快 | PS5,W4R [00:20:42] [00:21:48] |
| 深水 Lumen 剔除 | 超过 1 ms | PS5,W4R [00:35:18] |
| 分辨率链 | 主分辨率从 800p 到 1080p,次级分辨率为 1440p(4K 的 66.67%),动态分辨率为 55% 到 75%;次级分辨率节省约 1 ms | W4R [00:43:08];OZ26 [00:15:48] |
| 流送 | 引擎默认值为 5 ms;统一后为 2.5 到 1.5 ms(延迟减少 40%);最终为 0.8 ms;示例中从请求到可见需 51 帧 | OZ26 [00:25:25];W4S [00:22:13] [00:23:55] [00:32:18] |
| 人群 | NPC 从 300 个降至 200 个:游戏线程耗时 11.5 ms,有 5 ms 余量 | PS5,W4R [00:16:53] |
| UObjects、GC | 少于 500k 为佳,超过 1M 有问题;GC 耗时 1 ms 没问题,2 ms 需隔离分析,10 ms 需调查 | HITCH [00:39:06] [00:39:39] |
| 生成 | 每帧一个复杂 Actor | 低端目标平台,HITCH [00:25:29] |
质量门槛
可量化指标:各阶段中位数以及精简路线的每帧耗时均低于 16.67 ms(NORSE [00:29:51])、百分位数
和 VSync 错过率(OZ26 [00:45:55]);冷启动时无卡顿快照;P.feature_budget_check 中没有无法解释的 over;每个已更改的 cvar 均读回验证;差值超出多次运行的波动范围,且采用相同的检查规范。视觉指标:每项取舍都提供相同摄像机视角的对照图;卡顿快照截图;视图仅用作定位工具。完整评分标准:references/critique.md。
常见错误
| 错误做法 | 表现 | 修正 |
|---|---|---|
| 在 PIE 中进行性能分析 | 蓝图和 CPU 开销偏高 | 使用 cooked Test 构建;仅在编辑器中排查 GPU 问题(FFW [00:04:29]) |
| 开启动态分辨率时查看 GPU 毫秒数 | GPU 时间接近预算,但分辨率下降 | 锁定为 75%(NORSE [00:44:40]) |
| 想当然地认为异步计算有效 | 各通道耗时总和超过一帧;没有可重叠内容的通道开销反而更高 | 仅使用 r.RDG.AsyncCompute 0 进行归因;逐项功能进行 A/B 测试(W4R [00:21:48]) |
| 归咎于最长的条形 | GameThreadWaitForTask 耗时 34 ms | 继续追查渲染、RHI 或工作线程(KEN [00:16:30]) |
| 60 fps 目标下使用 Epic 可伸缩性设置 | sg.* 显示 3 | 在设备配置文件和编辑器设置中设为 2 级(OZ26 [00:12:01]) |
sg.ResolutionQuality=2 | 分辨率为 2% | 这是百分比 [added] |
| 直接将 TSR 用于 4K | 后处理通道以 4K 运行 | 使用 1440p 次级分辨率,并进行空间升频(W4R [00:42:33]) |
| 首先查看 Nanite Overdraw 视图 | 追着白色像素排查 | 先查看预算、Evaluate WPO 和 Pixel Programmable,最后查看 Overdraw(OZ24 [00:32:13]) |
| 长阴影的一半在动画 | WPO 植被阴影在某个裁剪映射处断开 | 提高 r.Shadow.Virtual.Clipmap.WPODisableDistance.LodBias(OZ24 [00:46:49]) |
| 移动角色上的 VSM 局部光源 | 动态页面每帧都失效 | 对这些光源进行光线追踪阴影 A/B 测试(AVW [00:26:25]) |
| 下雨或深水 | Lumen 反射和水体开销增加 | 下雨时重新查看 Performance Overview,并限制粗糙度;设置水体不透明深度截断(OZ24 [00:40:40];W4R [00:35:18]) |
| 归咎于 PSO,或在预热后测试 | 修复方向错误;第二次运行时卡顿“消失” | 根据跟踪特征分类;使用 -clearPSODriverCache 进行冷启动测试;主机平台跳过(PSO blog;HITCH [00:35:50]) |
| 一帧内生成一波对象 | SpawnActor 峰值 | 限制每帧生成数量,启用 Tick Animation On Skeletal Mesh Init,按类型使用对象池(HITCH [00:25:29] [00:27:26]) |
| 摄像机切换峰值 | 切换后的下一帧出现过度绘制 | r.Nanite.PrimeHZB(5.7)[verify](W4R [00:44:44]) |
| 一次进行多项更改 | 无法归因性能提升 | 使用 ChangeLog,每次运行只做一项更改 |
| 对发生碰撞的植被进行密度缩放 | 游戏玩法发生变化 | 仅对不发生碰撞的类型进行缩放(FFW [00:32:48]) |
| 默认使用复杂碰撞 | 对 200 万三角形的回退网格进行逐多边形查询 | 从第一天起就使用 Use Simple as Complex,批量更新旧网格,并处理 Nanite 回退(OZ26 [00:07:23] [00:37:15];HITCH [00:15:58]) |
| 将“静态”道具保留为 Movable | 约 1,000 个网格导致性能下降 20% | 审查移动性设置(ARG [00:11:54]) |
交接
接收来自 scenario-unreal-pipeline-automation 的构建和路由,以及来自所有队友的内容。 交付诊断报告和 JSON 更改请求,并附带测得的差异和一致性截图:
- scenario-unreal-world-building:组件数量、Packed Level Actors、ISM 单元转换器、 FastGeo、HLOD、移动性、碰撞、植被距离。
- scenario-unreal-materials:遮罩、PDO 和 WPO Nanite 材质、最大 WPO 位移、 Displacement Fade、着色分箱、After DOF 半透明、贴花。
- scenario-unreal-lighting-rendering:Lumen 阈值、RT 场景和远场、Lumen Lite、VSM 设置、光线追踪局部阴影、DF 阴影;批准画质权衡。
- scenario-unreal-gameplay:Tick、重要性、生成和对象池、阻塞式加载、重叠、UObject 数量。
- scenario-unreal-animation:Animation Budget Allocator(已注册组件)、AnimBP 冗余、 MetaHuman LOD、人群数量。
- scenario-unreal-vfx:Effect Types、对象池、Data Channels、GPU 回读、效果中的投影光源。
- scenario-unreal-cinematics:镜头切换卡顿、电影级可伸缩性。
- scenario-unreal-pipeline-automation:设备配置文件、验证器(阻塞式加载节点、绑定 规则)、夜间性能测试。
UE 5.8 说明
- 新工具:
snapshothitches -start|-stop(需要stat default)、TraceQuery JSONL(架构 [待验证])、UObject Count 计数器、World Partition Insights(Spatial Profiler)、stat unit仅在独立 GPU 上显示显存、ProfileGPU 管道等待和r.ProfileGPU.TableFormatting 0(rn58;TL 第 2 部分)。 - Lumen Lite Beta 版,画质为 Medium;MegaLights 已可用于生产;VSM 延迟失效预算;自 5.7 起,方向光默认启用接收器遮罩;植被类型支持 Nanite Pixel Programmable Distance;
r.Nanite.PrimeHZB自 5.7 起可用。 - FastGeo 和 5.6 中的流送控制台变量仍为 Experimental(请查看插件浏览器)。
- Mac:仅支持 Apple Silicon;Nanite 和 VSM 为 Beta,Lumen HWRT 和 MegaLights 为 Experimental(M2+); Insights 不提供 ContextSwitch,也不列出内存调用栈;在 Xcode 和 Instruments 中查看 GPU“原因”(MOB)。
参考资料
references/expert-notes.md:按专家整理的原则,附时间戳、 不同意见和判断条件。references/procedures.md:P0 至 P11,以及 P5b、P6b(可疑树)、 P7b(流送)、P9b(镜头切换),包含完整代码、测试路径和状态。references/critique.md:捕获、诊断、修复和验证的评估标准。references/gui-paths.md:供计算机操作 Agent 使用的 Insights、编辑器和 Xcode 路径。references/sources.md:来源、凭据、最佳时间戳、修订历史。scripts/ue_perf.py:规划、A/B 规划、跟踪分析、可疑树、解析器、配置写入器、验证、审计。