
1. 为什么Unreal Insight的启动项直接决定了你能看到多少性能真相先讲一段我自己的经历。去年优化一个开放世界项目玩家反馈某个区域跑一会儿就掉帧而且掉得很诡异不是一直卡是隔几十秒卡一下。团队里有人猜贴图流送有人猜GC还有人说是粒子系统泄漏。开了一整天的会谁也说服不了谁。后来我把本地的Unreal Insight启动项加上完整通道参数重新跑了一遍那个区域整个时间线拉出来一看问题根本不在渲染也不在GC而是远处一棵树的伏笔导航网格定期重建把一个后台线程打满了。这个排查过程里Unreal Insight的详细数据通道功不可没——但前提是你得先知道怎么把启动项配对。很多人对Unreal Insight的印象停留在“编辑器里有个窗口能看帧率曲线”实际上它是一套完整的性能追踪系统由两部分组成游戏端负责采集数据分析端负责回放和可视化。游戏端什么时候采、采哪些通道、文件存到哪里全由启动项决定。换句话说你看到的性能真相上限就是启动项配置的上限。默认配置只开了一小部分通道很多关键数据根本没录进去。这个主题适合谁我觉得只要你用虚幻引擎做项目不管是单人开发还是团队协作都值得花半小时把启动项这套东西吃透。尤其是那些经常被“为什么卡一下找不出原因”折磨的人这篇文章就是给你的。下面我按“是什么、怎么配、踩过什么坑、怎么用顺”这个顺序把我自己的经验全部摊开。1.1 一套采集系统两头都要配启动项Unreal Insight这个工具链里“启动项”这个概念经常被混着用其实它包含三个层面的东西。第一层是游戏进程的命令行参数。比如你启动打包出来的exe时后面跟的参数。这一层控制的是游戏端要不要录数据录哪些通道录完放哪。第二层是开发环境下编辑器的启动参数。你在虚幻引擎快捷方式或者批处理里传的参数决定编辑器启动时是否挂载trace采集。第三层是UnrealInsights分析端自身的启动参数。比如它监听哪个端口是否开启自动保存会话是否开启服务端模式等待游戏端连接。我在实际项目里经常遇到这种情况团队里有人把编辑器的快捷方式加了-trace参数结果分析端一直没开游戏端一直往一个不存在的地址发数据帧率还因此掉了不少。后来我说服大家把启动项统一写在批处理脚本里谁要用一致的文件内容直接双击就行再也没出过这种乌龙。所以我建议你把这篇文章看完后第一件事是去团队里统一一套启动项模板避免各配各的。1.2 为什么默认配置不够用你可能会想既然Unreal Insight是官方工具默认配置应该够用吧答案是默认配置只适合“看一眼大概”不适合做深入分析。原因是trace通道的设计思路本身就强调按需采集。全开通道会带来采集端的性能开销而且生成的海量数据文件也非常大。我遇到过一份半小时的trace文件解压后有12GB分析端打开等了十分钟才出图。默认配置只开启CPU、GPU、Frame等几个基础通道像AssetLoadTime、Net、Concurrency这些在多人项目中很关键的通道默认都是关闭的。这就引出一个核心观点**详细数据启动项不是让你把全部通道都打开而是让你根据要排查的方向精确选择数据源。**比如你怀疑资源加载导致卡顿那AssetLoadTime和Loading通道比什么都重要你怀疑网络同步有问题那Net通道是你的主角你怀疑多线程调度问题Concurrency通道才帮得上忙。选对了通道数据才有指向性才不会在打开报告后看得一头雾水。2. 启动项参数逐项拆解-trace只是开始我自己刚开始用的时候只知道一个-trace参数以为加上它就能拿到所有数据。后来看报告才发现仓位里空荡荡的很多想看的区域一点信息都没有。这篇我会把所有常用参数分为三组来讲基本开关组、通道控制组、文件与连接组。每一组里哪些参数是必须的哪些只是锦上添花都给你标出来。2.1 启动开关与文件位置先把数据落下去先看最基础的一组参数它们决定采集系统是否运行、数据写到哪里。参数作用说明我的建议-trace启用trace采集系统来源数据开始记录必加不加的话后面所有通道参数都无效-tracefileC:\xxx.utrace指定trace文件完整路径和文件名建议固定一个输出目录方便查找-tracefiletimestamp在文件名后自动追加时间戳非常推荐可以避免覆盖历史数据-traceformats指定保存格式通常是trace或csv可组合需要导出分析报告时用csv平时不用这里面最容易出错的就是-tracefile的路径。Windows下如果路径里带了反斜杠加参数时不需要额外转义但如果用了引号包裹整个路径注意命令行环境下引号的配对问题。我建议统一用正斜杠做路径分隔符比如-tracefileC:/Profiles/run1.utrace这样在批处理和编辑器里都不会出怪问题。还有一个细节-tracefiletimestamp生成的文件名是这样的——MyGame_2025.01.10-14.30.22.utrace。如果不同时加这个参数两次启动会覆盖同一个文件。我在项目里吃过这个亏辛辛苦苦跑了一个场景结果第二次测试把第一次的trace数据覆盖了早上录的数据下午才发现已经被新的文件顶掉。加了时间戳之后这个问题彻底根治。2.2 通道选择的艺术数据可不是越多越好通道是Unreal Insight最核心的概念。它把各种运行时事件分门别类每个通道就是一组相关事件流。启动时用-tracechannels参数指定要打开的通道多个通道用英文逗号分隔。下面是我在实战中经常用的几个通道按使用频率排序Cpu各线程的CPU耗时帧率分析的基础数据源GpuGPU渲染耗时检查渲染瓶颈就看它Frame帧事件整帧的开始与结束标记常配合Cpu、Gpu做对齐Log日志输出流能把游戏运行时的Log全部回放出来Bookmark书签标记配合控制台命令主动标出关键时刻LoadTime资源加载耗时排查加载卡顿时的首选AssetLoadTime单个资产的加载明细能定位到具体某个贴图或网格Net网络同步数据多人联机项目基本必开Concurrency多线程并发调度情况查后台线程问题极有用Diagnostics增强诊断信息偶尔开一下看有没有警告这里我说一个很多新手容易踩的坑通道名称是区分大小写的。有次我写了个-tracechannelscpu,gpu小写开头结果分析端里CPU和GPU两个区域全是空的。后来查文档才发现正确写法是Cpu,Gpu,Frame。你的启动参数里如果写了不存在的通道名Unreal引擎不会报错它只是默默忽略掉让你查问题时一头雾水。我建议你第一次配置时严格对照文档写一遍确认大小写和拼写。2.3 动态控制的启动后命令不只靠启动时配置启动参数只能管游戏启动的那一刻。等游戏跑起来之后你还可以用控制台命令动态开关通道这些命令通常通过-ExecCmds在启动时注入或者运行中用~键打开控制台手动输入。最常用的几个命令trace.start开始录制trace.stop停止录制trace.channel Cpu单独打开某个通道trace.channeloff Net关闭某个通道trace.bookmark 描述文字在时间线上打一个书签标记我自己的习惯是在Startup命令里执行trace.bookmark Init complete在进入战斗场景的触发点再打一个标记这样回放时就能快速定位到两个关键节点不用在几万帧里费劲找位置。命令行触发书签这种事熟练了以后你会觉得像是给时间线贴便签纸非常方便。另外-ExecCmds可以接受多个命令用分号分隔。你可以一次性注入多个开关比如-ExecCmdstrace.start; trace.channel Log; trace.bookmark startup这个写法像极了Windows下用cmd命令来配置开机启动项的思路——都是把一组命令打包好在启动时统一执行。如果你对开机启动项的习惯很熟你会很快上手。3. 从一行参数到报告导出完整跑通一次详细数据采集理论知识讲完了下面进入硬核操作环节。我会以一个Windows下的打包游戏为例从写启动参数开始到分析端打开报告、导出数据完整走一遍。你照着操作至少能跑通一个能够回放的trace流程。3.1 游戏端参数组合实例与脚本模板先看我常用的一个批处理模板文件命名run_capture.bat放在项目根目录echo off set TRACE_DIRD:/GameProfile/%USERNAME% if not exist %TRACE_DIR% mkdir %TRACE_DIR% start D:/Game/MyGame.exe ^ -trace ^ -tracefile%TRACE_DIR%/MyGame_%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%.utrace ^ -tracechannelsCpu,Gpu,Frame,Log,Bookmark,LoadTime,AssetLoadTime ^ -ExecCmdstrace.bookmark test_start ^ -stat这里有几个设计细节值得说明一下把trace目录按用户名区分好处是多人共用测试机时不会互相覆盖文件文件名里嵌入了日期和时间戳我习惯用%date%和%time%做拼接简单直接不用额外安装工具加了-stat参数这样游戏运行界面上会实时显示性能统计方便你确定当前是否在正常的测试起点-ExecCmds在启动时立即执行trace.bookmark test_start回放时你一眼就能看到游戏从哪一帧开始的跑测试时我通常会让游戏自动进入场景或者手动走到目标区域然后用控制台命令打几个Bookmark。等你觉得关键动作都做完了退出游戏trace文件会自动保存并关闭。3.2 分析端本地打开文件与远程连接两种模式trace文件拿到手之后就是分析端的活了。UnrealInsights分析端通常在引擎目录下可以找到路径大概是Engine/Binaries/Win64/UnrealInsights.exe。分析端有几种打开trace文件的方式直接启动UnrealInsights.exe然后在界面的Session列表里找到对应的游戏会话如果游戏已经连上它把.utrace文件拖进UnrealInsights窗口用命令行方式直接指定文件UnrealInsights.exe -OpenTraceFileD:/GameProfile/xxx.utrace我个人更喜欢用第三种方式因为这个可以写进批处理脚本一条命令打开指定文件不用每次都手动拖拽。你也可以在分析端的设置里把默认工作目录改成自己的trace输出目录打开时文件列表就在你眼前。数据加载后你会在Timing Insights界面看到多条水平时间线每条对应一个线程或者一个通道区域。竖着看是同一时刻不同线程的耗时情况横着看是随着时间推进的性能变化。最顶上的区域是帧时间概览红色高亮的就是长帧长帧越多说明卡顿越严重。这个界面信息量非常大第一次接触的人很容易晕。我给你一个上手顺序先看顶部帧时间曲线找出卡顿区间然后按住鼠标左键框选卡顿区间的几帧接着看CPU各线程面板找哪个线程在那个区间出现过高峰。这个过程通常能解决七成以上的卡顿问题。3.3 把报告导出给团队伙伴有时候问题不在你本地你需要把trace文件和分析结果发给别人。导出功能在分析端里做得比较齐全你可以导出完整报告或者截图当前视图。我常用的是Export report它会把当前分析的概览数据打包成HTML文件包含帧时间、线程摘要、主要耗时统计等信息。这个文件给不懂工具的同事看一眼就能明白问题大致方向。完整trace文件本身也建议保留在共享盘或者对象存储里因为HTML报告里能看的东西有限真正深入排查还是得回到utterance文件里重新分析。导出时有一个注意点UnrealInsights的版本和游戏的引擎版本必须基本一致否则可能出现“版本不兼容无法打开”的提示。我遇到过同事用UE5.3的分析端打开UE5.2项目的trace文件结果白屏了好几次。建议项目里统一使用同一个引擎版本或者至少保证分析端版本不高于游戏引擎版本太多。4. 详细数据采集经常遇到的坑我的排查链路全记录这条是我最想分享的部分。无论参数怎么配实际跑起来总有一些意外情况。下面这三个问题是我在带团队时遇到过的、也比较典型的问题我把完整排查链路写出来你遇到类似情况时可以按同样思路走一遍。4.1 完全没有任何文件生成先别急着怪启动参数现象游戏跑完了指定目录下没有.utrace文件。我第一反应是启动参数写错了。后来发现80%的情况不是参数的问题而是游戏进程根本没起来或者启动后立刻被安全软件拦了。所以排查链路是这样走的确认游戏进程真的运行了。用进程管理器看有没有MyGame.exe截图或记录下来确认命令行参数真的传进去了。在批处理里临时加一行echo %*把参数打出来看一眼检查trace输出目录是否可写。目录不存在时有些构建版本不会自动创建目录你得提前手动建好确认运行环境。打包出来的游戏如果是Shipping构建trace采集某些通道会被裁剪掉最好先切到Development构建有一次我排查半天发现是杀毒软件实时扫描把.utrace文件删了。因为文件名里有日期时间戳每写一个新文件杀毒就扫描一次文件写了一半就被拦停。解决方法是把trace目录加入杀毒豁免列表。这个坑非常隐蔽没有日志提示你只能靠逐步排除法确认。4.2 文件生成了但打开后数据残缺不齐现象文件大小只有几十KB打开后只有几帧数据其余全是空白。这个问题的根源通常是通道配置或者内存缓冲设置。trace机制默认使用一块内存缓冲区把数据暂存然后异步写入磁盘。如果你的游戏运行期间大量生成trace事件缓冲区满了之后系统会按照策略丢弃部分事件最后落盘的数据自然就残了。我的排查链路先看文件大小。如果明显小于预期比如就几十KB大概率是缓冲区不够或者写入线程被拖慢检查磁盘是否满了。trace文件写入需要连续空间磁盘余量不足时写入进程会频繁等待尝试调大缓冲区。可以在启动参数里使用-tracebuffer64单位是MB。这个参数不是万能的但能缓解缓冲溢出问题如果在编辑器里跑trace给编辑器也加上-tracebuffer因为编辑器本身开销大更容易满缓冲另外要注意游戏退出时的表现。有些时候你看着游戏窗口关了但后台进程还在慢慢写数据。如果这时候你立刻删掉了进程trace文件可能只写了一半。我见过好几个同事关掉游戏马上关电脑结果第二天发现文件损坏。建议关闭游戏后等几秒再操作。4.3 连接分析端握手失败远程采集时最熟悉的陌生人现象游戏端加了-tracehost192.168.1.100分析端也开了但Session列表里就是看不到游戏进程。这个我遇到太多次了尤其是在虚拟机或者多网卡机器上。排查链路如下先确认两台机器能ping通。注意不是看通不通而是看延迟和丢包。偶尔有防火墙拦截回显请求ping不通不代表网络不通但ping通了至少说明网络层是通的确认分析端监听端口。UnrealInsights默认监听端口是1989如果你改了端口游戏端也要用-tracehostIP:端口格式指过去检查防火墙。分析端机器上Windows防火墙默认不会放行1989端口你需要手动添加一条入站规则如果游戏和分析端在同一台机器直接用-tracehost127.0.0.1不要用机器名避免DNS解析问题最后一步很容易被人忽略。有些公司的内网DNS解析很慢机器名解析超时之后连接就失败了。直接用IP地址能绕开这一层。我自己写的所有脚本和批处理里一律写IP不写机器名。还有一种情况是游戏端和分析端都正常但分析端界面保持在某个旧会话视图新会话进来后列表没自动刷新。这个不算网络问题你手动刷新一下会话列表就好。5. 把详细数据采集变成日常习惯工作流设计与进阶技巧启动项配置跑通一次不难难的是把它融入日常开发流程让团队每个人都能顺手采集到有用的数据。我最后分享几个工作流层面的技巧用完你会发现效率提升非常明显。5.1 用批处理组合多个测试场景我们项目里现在有一套标准化的trace采集脚本按场景命名比如capture_forest.bat、capture_battle.bat。每个脚本里除了基本启动参数还会通过map参数直接加载对应关卡自动跑一段固定的穿过路径。这样任何人想采集某个场景的数据双击脚本就行不用手动进游戏再传送。模板大致是这样start D:/Game/MyGame.exe ^ -trace ^ -tracefileD:/Profiles/forest_%time:~0,2%%time:~3,2%.utrace ^ -tracechannelsCpu,Gpu,Frame,Log,Bookmark,LoadTime,AssetLoadTime ^ -ExecCmdsopen ForestMap?gameCaptureFlowGameMode; trace.bookmark loaded ^ -stat这里的open ForestMap是虚幻引擎控制台命令启动后直接把地图加载出来。?gameCaptureFlowGameMode指定一个专门用于采集的游戏模式。路径上沿路的关键节点你可以在蓝图或代码里用TraceBookmark节点主动打点这样回放报告里会自动出现“进副本”“交互触发”“Boss出现”等可读标签。5.2 在代码里主动打点比手动按控制台靠谱手动在控制台敲trace.bookmark太依赖运气。更可靠的方式是在蓝图或C代码里主动埋点。C里你可以这样写#include Trace/Trace.h UE_TRACE_EVENT_BEGIN(Custom, FPSDropCheckpoint) UE_TRACE_EVENT_END() // 在关键逻辑处调用 UE_TRACE_LOG(Custom, FPSDropCheckpoint)蓝图侧更简单有一个节点叫Unreal Insight Bookmark直接调用它并传入一个字符串描述就会在时间线上生成一条书签。我把这些节点放在关卡流送完成事件、战斗触发事件、UI打开事件等位置采集出来的数据天然带业务语义分析时几乎不用猜。有人可能会担心埋点的性能开销实际上引擎在设计时已经说得很明白Bookmark这类事件开销极其微小。在正式发布版本里trace机制默认是关闭的只有在启动参数带-trace时才采集所以完全不用担心影响最终玩家体验。5.3 从一张报告图定位到一个阻塞线程的实战案例再举一个实战例子收尾。有次团队做多人模式玩家反馈联机时偶尔会卡一千多毫秒单机一点事没有。我拿到报告后先看帧时间曲线果然有几次尖峰峰值达到1200ms。然后把Net通道打开看网络往返时间尖峰同步出现。看起来是网络问题。但继续往下看线程分布发现有一个后台线程叫GameplayThread在尖峰时间点占用几乎打满。再跟一下Bookmark尖峰前的场景里正好有多个玩家同时从存档点重生而存档点的加载逻辑里有同步资源加载调用千毫秒级的卡顿就是这么来的。你猜用什么优化方案解决的很简单把同步加载改成异步加载等待加载期间用占位资源。改完再跑一遍同样的操作下尖峰彻底消失。整个排查过程从看到报告到定位到代码一共只用了二十分钟。换做以前靠肉眼看游戏画面猜原因少说也得一周。这就是为什么我愿意花这么多篇幅讲启动项配置数据链路配好了工具就是照妖镜配不好再好的性能分析工具也只是摆设。希望这篇文章能帮你把照妖镜架好以后遇到性能问题直接拿数据说话别在那里感情用事猜来猜去。