mcpField
S
scenario-unreal-performance

scenario-unreal-performance

github.com/scenario-labs开发1.2k198 次安装1 天前更新
代码仓库

关于 scenario-unreal-performance

面向 Unreal Engine 5.8 项目性能工程的技能,指导工程师测量、诊断并验证性能问题。以阶段毫秒数、可重复的同路线捕获和独立卡顿分析为核心。

主要功能

  1. 01按游戏线程、渲染线程和 GPU 分类瓶颈
  2. 02规划基准捕获并分析 Trace
  3. 03测量配置与渲染功能的性能变化
  4. 04审计关卡和资产设置
  5. 05单独诊断卡顿并验证修复

适用场景

  1. 01定位目标硬件上的帧时间瓶颈
  2. 02比较 Lumen、Nanite 或 VSM 的性能成本
  3. 03排查关卡加载、GC 与生成造成的卡顿
  4. 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.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
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 事件轨道。

  1. 探测工具。 使用 job_probe_perf.py 查询 API 名称和 cvar;对第一个 TraceQuery 输出调用 P.schema_probe(jsonl)。GATE:每个计划使用的 cvar 都打印出了值;TraceQuery 的键均已映射。
  2. 明确差距,设定预算。 38 fps 对应 26.3 ms,比 16.67 多 9.6 ms。 P.budget_table(platform, fps, pass_budgets)(OZ26 [00:45:55])。GATE:每一行都有来源,各阶段的通道预算合计不超限。
  3. 确定路径并进行真实采集。 使用 P.route_from_bugit(log)(打包时使用 P.route_event_track),P.capture_plan("budget", ...),运行三次。GATE:三次精简运行,已知性能波动,且采集规范一致。
  4. 分类。 P.diagnose_bound(frames, 16.67, context=...) 会给出瓶颈、差距、注意事项和下一次采集方案;读取可扩展性设置(P.stat_sequence("scalability_readback"))。GATE:已标明瓶颈,差距以 ms 为单位,且已解答注意事项。
  5. 优先调整配置,每次测量只改一项。 设置 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 测试。
  6. 针对瓶颈进行深入分析(步骤 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:每个超预算类别都有明确的原因、资产和负责人。
  7. 审计并分派修复任务。 使用 P.perf_audit_level()、P.perf_audit_assets()(移动性、碰撞来源、WPO 边界、Displacement Fade),通过 P.change_requests(rows) 将请求分派给负责人;达成一致后再应用。使用相同的 BugItGo 视图检查一致性(P.parity_pair)。GATE:所有 needs_eyes 对都经过目视判断。
  8. 卡顿分析。 先冷启动再热启动执行 capture_plan("hitch")(冷启动仅在非控制台平台上);使用 P.hitch_snapshots(dir),并将每个快照交给 P.analyze_trace;对路径中的剪切点使用 P.camera_cut_spikes;将未分类的帧交给采样分析器。GATE:冷启动路径没有快照,游戏过程中没有阻塞加载,GC 事件低于 2 ms,UObject 数量低于 500k。
  9. 验证并设防。 使用相同的路径、构建版本和设备;每项运行三次;采用选定的异步计算方案;锁定 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 msPS5,W4R [00:35:18]
分辨率链主分辨率从 800p 到 1080p,次级分辨率为 1440p(4K 的 66.67%),动态分辨率为 55% 到 75%;次级分辨率节省约 1 msW4R [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 规划、跟踪分析、可疑树、解析器、配置写入器、验证、审计。

评论

支持 Markdown