
1. 为什么性能优化要从项目设置开始先说点实在的。我见过太多团队项目干到中后期场景里随便摆点东西帧率就往下掉然后一群人开始疯狂压DrawCall、减贴图、合并材质、砍特效。折腾一两个星期帧率回来了但画面也秃了美术开始骂人程序开始改需求两边扯皮。其实这些痛苦大部分本该在项目启动的头两周就规避掉。UE5的性能优化和其他引擎有个不太一样的底子它的默认设置是为“高端PC和主机”服务的甚至可以说是为“演示级画面”服务的。Lumen、Nanite、虚拟阴影贴图Virtual Shadow Map、硬件光线追踪这些功能默认打开或者很容易被误开任何一个放到移动端或者中低端PC上都是性能黑洞。你如果在项目初期不把这些底层的、全局的东西定死后面每一个场景、每一个材质、每一盏灯都可能踩雷。所以做性能优化的第一课不是学怎么调帧率而是先把Project Settings里那一堆开关的默认行为搞清楚。因为项目设置的改动成本是全周期最低的引擎还没跑起来数据量还没堆积美术资源还在白模阶段你花两天时间把设置链路理顺后面所有人都受益。反过来等项目做了一半再回头改这些东西往往要动资产、动材质、动光照方案那成本就不是两天能抹平的了。这篇笔记是我自己项目里实际梳理的结论主要覆盖三块怎么给自己定性能预算、Project Settings里哪些开关是关键、不同目标平台怎么选渲染架构。这一篇先把底子打牢后面再扯具体的优化手段和工具链。2. 摸底三件套目标平台、帧预算与硬件基准2.1 先问自己三个问题再动设置我每次接手一个UE5项目第一件事不是打开引擎改配置而是先问三个问题目标平台是什么是纯PC、纯主机还是PC主机移动端全平台目标帧率是多少30帧、60帧还是120帧不同帧率对应的帧预算完全不同。最低配置基准是什么你打算让什么样的机器跑得动是五年前的入门本还是近两年的中高端台式机这三个问题不回答清楚所有设置都只是“看着差不多”的拍脑袋。举个例子如果你做的是PC单机游戏目标60帧那你的单帧预算就是16.6毫秒。这16.6毫秒不是均匀分给GPU就完事了CPU侧的游戏逻辑、动画系统、物理系统、网络同步都要占一部分。我习惯的做法是先把CPU侧的GameThread预算卡在4到5毫秒渲染线程留1到2毫秒GPU侧留10到11毫秒。这样即使中间某些帧出现峰值也不会直接跌到30帧。如果是移动端30帧就是“能玩”的下限60帧是“体验好但压力大”的档位。4毫秒的GPU预算留给复杂的半透明粒子一点多余空间都没有。你在移动端做半透明面片大爆炸特效做的时候很爽真机上直接变幻灯片的节奏。2.2 用最普通的机器做基准不用你的开发机还有一个特别常见的坑团队开发机清一色顶配2080、3080起步16核CPU64G内存。项目设置按这个机器的性能去调测出来全绿结果跑到用户的中端机器上直接不能看。我的做法是项目立起来就定一台“基准机”这台机器模拟的是目标用户里最差的那一档配置。不求它跑满画质但至少能在你的最低画质预设下稳定跑到目标帧率。这台机器不用多好比如移动端就找一台两年前的主流安卓机而不是最新的旗舰PC端看看Steam硬件调查里占比最高的那档配置照着搭一台就行。把基准机摆在测试桌上之后项目设置凡是动了跟性能有关的开关都在这台机器上重新测一遍帧率。设置这东西不是一次调完就一劳永逸的随时会被人改回去养成每轮改动都跑基准的习惯后面能省掉大量“帧率怎么突然掉了”的瞎猜。2.3 把帧预算写成文档贴给所有人看预算不该只存在程序脑子里要写成文档让美术、TA、策划都看得到。我项目里常用的一张表长这样平台目标帧率单帧总预算GPU预算GameThread预算渲染线程预算PC最低配60帧16.6ms11ms4ms1.5ms主机性能模式60帧16.6ms10ms4.5ms2ms手机中端30帧33.3ms20ms8ms3ms手机高端60帧16.6ms10ms4ms2ms表里的数字不用一开始就卡死它是动态调整的但每次调整都要有依据。什么依据就是后面会讲到的Stat单位和GPU Visualizer拉出来的实际数据。没有数据支撑的预算调整都是拍脑袋。3. Project Settings里那些“改了才知道”的引擎开关3.1 渲染模块的大方向Forward还是Deferred进入Project Settings第一个要定下来的是Rendering模块下的Shading Model和渲染路径。UE5默认用Deferred Shading延迟渲染配合Lumen做全局光照画质是很好但开销也高到吓人。移动端基本不用想跑Deferred Lumen等于自杀。如果你做的是移动端或中低端PC强烈建议切到Forward Shading前向渲染。前向渲染在UE5里叫Forward Renderer它的好处是可以用MSAA做抗锯齿延迟渲染用不了MSAA、对半透明物体更友好、带宽占用更低。代价是动态光源数量上限低太多实时灯光就得靠烘焙和间接光来补。那是不是PC和主机就一定用Deferred也不一定。如果你的项目是偏风格化的灯光数量少、氛围靠天光和烘焙贴图撑那Forward反而更划算。我做过一个PC端的风格化项目切到Forward之后同样的场景帧率直接涨了30%代价只是让我把场景里的灯光数从十几盏压到了四盏左右画面凭烘焙和反射捕获补回来了。3.2 全局光照方案Lumen、烘焙还是纯静态UE5的Lumen确实惊艳动态光照、无限反弹、间接光在房间之间流转一套下来很多场景可以不用手动摆反射捕获。但它的开销也很真实——性能模式下Lumen的GPU成本通常在3到5毫秒之间这还算保守的。你场景里再有半透明粒子、体积雾叠上来预算立刻爆炸。所以我的建议是分场景看面向移动端的项目Lumen直接关掉光照方案走烘焙Static Lights Precomputed Lighting。面向PC/主机的项目如果想保Lumen一定要在项目设置里把Lumen的Final Gather Quality和Mesh SDF细节调到合理档位不要拉满拉满只是让那些肉眼几乎察觉不到的细节吃掉大量GPU时间。关了Lumen之后记得把Reflection Method改回Reflection Captures同时在全场景铺反射捕获球否则金属材质和光滑地面会看起来很死。这一步没有捷径时间花在摆反射捕获上但换来的是帧率实打实的提升。3.3 默认画质设置别迷信“Epic”项目设置里有Default Scalability组比如全局的质量等级Scalability Level很多人直接选了Epic或者Cinematic觉得这样“能发挥引擎全部实力”。但说句不好听的这是赶工期和性能事故的主要来源之一。我的习惯是默认质量等级设在High甚至Medium先把游戏能跑顺然后把项目里真正的画面卖点比如主角的特效、关键场景的光照单独用Quality Switch或材质参数拉高而不是让整个项目全局拉满。这样目标机器跑不动的时候至少有个保底画质能用。另外材质编辑器里常驻的节点也别忘了检查。比如很多材质直接把Roughness连上了Noise节点这是实时计算的每个像素每帧都在算。如果这个材质还铺了大面积地面开销就很可观。遇到这种情况拓一个Texture Sample的粗糙度贴图哪怕512x512开销比在材质里算Noise低得多。3.4 阴影设置质量与性能差距最大的地方阴影是画面真实感的重要来源也是性能消耗的大头。项目设置里和阴影直接相关的开关主要是Virtual Shadow Map虚拟阴影贴图UE5默认开启。它的画质确实好但两级阴影级联加高分辨率的VSM在移动端是灾难级别的开销。我的习惯做法PC/主机高端画质保留VSM但把Shadow Map Resolution控制在2048或者4096视项目屏幕分辨率和场景规模来定。PC/主机中低画质切回传统的CSM级联阴影贴图设置里Shadow Maps选Per Object或者CascadedCascade的数量压到2到3级。移动端一律全关VSM用CSM都嫌贵的话直接方向光阴影贴图设一组然后静态物体统一走烘焙阴影。阴影之外还有个隐藏开销是Distance Field距离场它用来做软阴影和环境光遮蔽很漂亮但在场景物体多、结构复杂的时候等于是给每个物体都加了一层体积计算。移动端建议关掉PC端如果不是必须用也可以关掉换成屏幕空间AO。3.5 抗锯齿TAA不是唯一解很多人默认项目设置里Anti-Aliasing Method就用TAA因为UE5默认就是它。TAA在静态画面时效果很不错但一旦相机快速转动或物体快速移动画面就会发糊、有拖影。为了抵消TAA的模糊又有人去开更高的分辨率缩放比如150%的r.ScreenPercentageGPU成本直线上升实在得不偿失。对不同平台的建议是这样的移动端用FXAA或者直接Combined MSAA。MSAA质量好但开销随几何复杂度上升低端机多测几轮再做决定。PC风格化项目可以试试没有TAA的Deferred不带MSAA方案或者ForwardMSAA清晰度会好不少。PC写实项目TAA几乎跑不掉但可以配合DLSS或FSR把渲染分辨率降下来再靠超采样把画质推上去。抗锯齿方案没有“绝对最好”只有“在预算内能接受的质量”。每换一个方案至少花一个下午做同一场景的对比测试不能光看静止帧要看动态旋转镜头的拖影表现。4. 移动端与主机/PC的架构选择差异4.1 移动端Vulkan几乎必然是首选移动端图形接口的选择对性能的影响比很多人以为的大得多。UE5在Android上默认支持Vulkan和OpenGL ESiOS默认走Metal。就Android而言Vulkan的多线程渲染能力、CPU驱动开销和带宽管理明显优于OpenGL ES。如果你的Android包体最大的瓶颈在CPU侧的DrawCall提交那Vulkan基本上是救命稻草。我见过不少团队为了让老机型兼容还在用OpenGL ES作为主渲染API结果DrawCall稍微上来一点就帧率狂降。如果非要兼容老机型可以把OpenGL ES作为Fallback主API用Vulkan这样至少主流机器都能吃到Vulkan的红利。iOS那边没得选只有Metal所以主要考虑的是让UE5正确启用Metal的矢量指令和GPU Family特性。项目设置里对应的是Default Settings的iOS Renderer确认选的是Metal而不是OpenGL ES能跑Metal 3的机器就让它跑Metal 3不能用就跑Metal 2的Fallback。4.2 移动端的Targeted RHIs与Shader编译裁剪很多项目会忽略一个东西项目设置里Platform Android / iOS Targeted RHIs。这里面不是让你勾越多越好恰恰相反是让引擎只为你目标设备编译对应的Shader格式从而大幅缩小Shader打包时间和运行时缓存压力。比如Android端如果你确定目标都是Vulkan设备那Targeted RHIs只勾Vulkan就行了。你要是把OpenGL ES也勾上引擎会为每个材质编译两套Shader变体包体变大、加载变慢、首次进游戏卡顿也变长。移动端用户的第一印象分就被这种东西败光了。Shader变体的数量是另一大坑。材质的Feature Level、Quality Switch、材质开关参数每一个都可能产生变体。我建议在项目设置里开启Shared Shader Code共享同一份Shader库然后在打包前用Shader Compile Worker把变体预先编译完。不要指望玩家在真机上临时编译。2024年之后的UE5版本对Shader变体的管理和平台裁剪做得更好了但前提还是你自己要把Targeted RHIs和各平台的Targeted Hardware设对。4.3 PC/主机端的API选择DX11、DX12还是DX12 SM6PC端默认走DX11还是DX12会影响你能不能用Lumen/Nanite的一些高级特性也直接影响CPU侧的渲染提交效率。UE5项目设置里可以指定默认的RHI。DX11兼容性最好老显卡也能跑驱动模型简单CPU提交效率中等。如果你的项目是低门槛PC游戏或者目标用户旧机器占比高DX11是稳的选择。代价是Lumen、Nanite这些新特性的部分功能在DX11下使用了降级路径。DX12CPU提交效率明显更好支持网格着色器Mesh Shader、DXRDirectX Raytracing、Variable Rate Shading等特性。但DX12对GPU驱动的要求更高不是所有显卡都能跑得丝滑遇到Bug时排查难度也更大。我的习惯是PC端先用DX11跑兼容性测试再用DX12跑性能验证主推API和上限API分开。如果项目里有Nanite Lumen的写实场景建议直接DX12 SM6作为主要目标但在最低画质档用DX11做保底这样既照顾了新特性又没完全放弃老机器。4.4 主机端是“开卷考试”别自己加戏主机端看起来只有一个操作系统性能规格也固定好像最好优化。但主机上往往因为性能目标高4K or 2K60甚至4K120反而压力最大。主机平台的CPU和GPU之间有些共享带宽GPU吃不饱的时候CPU也受影响所以主机端尤其要看清哪个部分是瓶颈。以性能模式为例目标如果定在4K/60你先看看GPU是不是真的能撑住4K下的全分辨率渲染。撑不住的话直接动态分辨率设置里打开Dynamic Resolution Scaling让渲染分辨率随时间片负载波动。这比硬抗4K全分辨率要可靠得多。主机端还有一点容易被忽略帧率目标不是单纯调设置就完事的还要配合系统级的性能模式切换。比如提供“画质优先”和“性能优先”两档选项背后其实是同一套项目设置里的不同Scalability参数汇总但切换时要避免中途加载卡顿。这些都属于项目设置阶段就要留好接口的东西。5. 默认设置之外的编译期与代码侧隐形成本5.1 Shader编译时间是会用肉来还的项目设置里有很多和Shader编译相关的选项是影响日常开发效率的。比如不开启Shader编译Worker每次改一个材质都能让你干等几分钟。而真正对最终玩家产生影响的是首日Shader编译PSO缓存生成。UE5里开启Share Material Shader Code可以降低包体和运行时编译开销但前提是所有材质都通过公共的Shader库。此外项目设置里的Shader Pipeline Cache建议打开这样玩家第一次玩游戏时生成的管线缓存会落盘第二次进游戏就不再需要现场编译了。很多玩家反馈“第一次玩卡一下之后就好了”绝大多数就是PSO缓存没做好的表现。5.2 蓝图节点数量是隐形的性能税虽然这篇笔记讲的是项目设置但我必须提醒一句项目设置里有个节点的数量限制比如Blueprint Limits。节点太多、蓝图实例太复杂会让GameThread的负担不断积累。你可以在设置里调整蓝图使用的较优化选项比如关闭Notifies对GameThread的过度占用但最根本的解法还是写代码。我自己踩过的一个坑是用蓝图写了大量Tick事件每帧都在做视线检测和数学运算场景里几十个这样的蓝图同时跑帧率直接掉了8毫秒。后来把高频逻辑挪到C活用了TimerManager和事件驱动GameThread瞬间就松了。项目设置里有些选项看起来和蓝图无关但实际上和GameThread息息相关。5.3 类型化数据、Asset Registry与内存启动开销项目设置里还有个不起眼但影响很大的选项Asset Manager的Primary Asset Type和Asset Registry的扫描目录。如果你的项目大量使用软引用或者动态加载Asset Registry会扫描的内容越多编辑器启动越慢运行时动态加载的卡顿也越明显。我见过一个项目把整个Content目录都设为软引用扫描范围结果每次冷启动开编辑器要将近十分钟。后来把资源分类整理只在需要的目录开启扫描启动时间缩到了一分半。这类设置在“性能优化”话题里很少被讲到但对团队日常效率的影响比很多图形选项更直接。6. 用工具验证设置而不是用感觉6.1 Stat单位第一手性能数据项目设置改完之后一定要通过Stat命令验证而不是凭着感觉说“好像流畅了”。UE5的控制台命令里Stat unit是最常用的它会显示Frame、Game、Draw、GPU这四组毫秒数分别对应总帧耗时、GameThread、渲染线程和GPU耗时。看Stat unit的时候我一般会看这几行数据的变化如果Game耗时高瓶颈在游戏逻辑、蓝图、物理或网络项目设置里改图形相关选项救不了。如果Draw耗时高瓶颈在场景复杂度、DrawCall数量、渲染线程提交逻辑。如果GPU耗时高瓶颈在材质复杂度、光照、阴影、后期处理、分辨率等图形相关参数。很多团队跑过来跟我说“项目卡”我远程打一个Stat unit截图过去基本上一眼就定位到瓶颈方向了。项目设置的每一个改动最终都要在Stat unit上看到数字变化否则就是无效改动。6.2 GPU Visualizer与GPU ProfileStat unit只能看大体方向要细致分析GPU内部各Pass的消耗我用得最多的是UE5的GPU Visualizer控制台输入ProfileGPU。它可以列出当前帧GPU上每个Pass的耗时比如光照、阴影、BasePass、半透明、后处理等。有一次我排查一个场景看起来只是美术资源多帧率莫名掉了20%。用ProfileGPU一拉发现一个特别离谱的Pass——Ray Tracing Reflections占了4毫秒。查了半天是某个材质里误开了光追反射的开关。要是没有GPU Visualizer我真得靠猜猜好久。日常优化流程里我建议把ProfileGPU的数据导出或者截图存档。项目设置的每次调整前后各跑一遍ProfileGPU对比一下各个Pass的耗时变化直观而且有说服力。后续写性能周报、跟美术对齐资源预算的时候这些数据就是证据。6.3 移动端别忘了真机Profile项目设置阶段最容易出现的错觉是“编辑器里跑得动真机一定没问题”。UE5的编辑器预览走的是PC的GPU完全没法代表移动端。移动端的性能验证必须在真机上跑用Android的Profile工具或Xcode的Instruments抓数据。离屏渲染、分辨率缩放、半透明特效、Overdraw这些在PC编辑器里看起来人畜无害一旦上了GPU带宽严重受限的移动平台立刻现出原形。我踩过最狠的坑一个屏幕空间特效在编辑器里只要0.2毫秒以为毫无压力结果真机上直接吃掉2毫秒因为移动GPU填补率完全跟不上。从那之后所有后期特效和全屏Pass都养成了真机验证的习惯。7. 这一篇之后你还需要盯住什么项目设置解决的是一棵树的根和主干但树的枝叶——材质编辑器里的每根连线、蓝图里的每个Tick、场景里每一盏灯、每一张贴图——同样需要逐个检查。UE5的很多高级功能默认状态是为了匹配“演示级画质”而存在的商业项目跑到实际目标硬件上一定要有自己的策略。如果你手头正好在搭一个新项目我建议按下面这个顺序走一遍确定目标平台和帧率写性能预算文档。按平台定好渲染路径Forward/Deferred、全局光照方案Lumen/烘焙/纯静态、阴影方案VSM/CSM/烘焙。把抗锯齿方案固定下来移动端尤其不要用TAA拉满分辨率硬扛。Android走VulkaniOS确保MetalPC端写清DX11保底/DX12主推策略。开启Shader编译缓存、裁剪Targeted RHIs、管好蓝图复杂度。用Stat unit和ProfileGPU记录改动前后的完整数据把每一次优化落到数字上。这些步骤做完项目的底层性能基线就立住了。后面每一章的内容——不管是资源规范、材质优化还是场景剔除——都是在这个基线上做上层建筑。最后再分享一个我自己的小习惯每次改完项目设置我都会在本子里记一行“时间、改了什么、为什么改、数据变化多少”。项目周期长了这个本子比任何文档都有用因为很多设置当时看起来没问题过了三个月回过头来调的时候根本想不起当初为什么这样定。记下来省得后面反复试错。