资讯动态

UE4场景性能优化:LOD与静态网格体合并实战

发布时间:2026/10/14 8:58:21 来源:尧图企业网站定制
做场景性能优化的人大概都有过这种经历场景摆完编辑器里转一圈看着挺顺一打包到目标设备上帧率直接腰斩打开性能分析工具一看Draw Call 数量高得离谱三角面数也远超预算。这时候回头看资产会发现两个最容易被忽略的地方——静态网格体有没有做 LOD以及零散的小物件是不是该合并。这篇笔记就围绕 UE4 里LODLevel of Detail细节层次和静态网格体合并Merge Actors这两件事展开把我自己在实际项目里反复试出来的用法、参数含义和踩过的坑整理一遍。适合已经会导入模型、会摆场景但对性能优化还没形成系统方法的朋友也适合做移动端或 VR 这类对性能敏感项目的开发者参考。整篇不堆理论重点放在这个参数为什么这么设这个操作到底省下了什么。1. LOD 在 UE4 里究竟替你省下了什么1.1 从屏幕像素到三角面数的一笔账要理解 LOD得先接受一个事实一个模型在屏幕上占的像素是有限的超过这个像素密度的高模细节人眼根本看不出来但 GPU 照样要一个三角一个三角地画。举个具体例子一个远景里只有 30 像素高的箱子原始模型有 5000 个三角面那每个三角面平均还摊不到屏幕上的一个像素渲染它纯粹是浪费。LOD 的思路就是根据物体在屏幕上占据的比例切换到面数更低的版本近距离用高模中距离用中模远处直接用一个几十面的盒子。UE4 里判断该用哪一级 LOD的核心依据是一个叫Screen Size的值它大致等于物体包围盒在视口里的投影尺寸与视口高度或宽度取决于轴向的比值。默认情况下LOD0 对应 Screen Size 接近 1.0近距离物体占满屏幕LOD1、LOD2 依次递减到 0.1 甚至更低。你打开一个静态网格体资产在 LOD Settings 里能看到每一级 LOD 对应的 Screen Size 字段这个值就是切换阈值。关键在于这个阈值不是拍脑袋定的。如果 LOD1 的 Screen Size 设成 0.5意味着物体占屏幕一半高度时才切到中模那在大部分常规构图中模型都会保持在高模状态优化效果几乎为零反过来设得太大远距离的模型过早降低细节画面会明显糊掉或者出现模型塌陷。我的经验是先用自动计算再对着实际场景微调别一上来就手填。1.2 LOD 切换机制Hysteresis 为什么必须调很多人调完 Screen Size 就收工结果在编辑器里走动时发现模型在不同 LOD 之间反复横跳画面一闪一闪的。这不是错觉是切换逻辑缺少缓冲造成的。UE4 提供了一个叫LOD Hysteresis的参数它的作用是给切换加一个迟滞区间物体进入某个 Screen Size 时切到低模但退回去时要超过一个略大的阈值才会切回高模避免在临界点上抖动。默认 Hysteresis 值一般是 0.02 左右对于静态镜头或者摄像机移动较慢的项目够用。但如果你的项目里相机移动很快比如竞速、飞行类或者有大幅度的镜头推拉这个值要往上调我一般会试到 0.05 到 0.1 之间具体看抖动是否消失。这里有个容易忽略的点Hysteresis 调太大也会带来问题就是物体本该切回高模的时候没切回来近处看会有一小段时间是糊的所以它本质是在抖动和延迟之间找一个平衡点。另外LOD 之间的过渡方式也值得说一句。默认是硬切换Popping即在那一帧直接从 LOD0 跳到 LOD1肉眼看就是模型啪地变了一下。UE4 支持LOD Transition也叫 Dithered LOD Transition开启后会用抖动图案让两级 LOD 短暂叠加淡入淡出。这个功能需要在材质里勾选对应选项才生效代价是多一层混合开销。对于写实向项目、室内场景硬切换往往能被遮挡物掩盖掉但对于开阔的大场景我建议打开过渡观感提升很明显。1.3 自动生成 LOD 的 Reduce Settings 该怎么动UE4 内置了自动生成 LOD 的功能导入模型后可以在 LOD Settings 里勾选Auto Compute LOD Distances并设置Number of LODs引擎会自动帮你塌陷出几级低模。这背后的算法大致是顶点聚类加边塌陷理解它不需要深入论文但Reduce Settings里的几个参数必须会调否则自动生成的 LOD 经常不能看。Percent Triangles保留的三角面比例LOD1 一般给 0.5 到 0.7LOD2 给 0.25 到 0.4LOD3 可以压到 0.1 左右。这个值越小模型越轻但形变越严重。Max Deviation允许的顶点与原网格的最大偏移量值越大越激进模型塌陷风险越高。Welding Threshold焊接阈值先把靠得很近的顶点合并再简化对硬表面模型影响很大。实际调的时候有个技巧自动 LOD 对有机形态比如树木、石头、布料效果还不错因为这类模型的细节本来就是模糊的但对硬表面模型机械、建筑、道具非常容易出问题因为它们的轮廓线特征强一旦顶点被合并直角就变成了斜角边线直接歪掉。我做过一个金属箱子的道具自动生成到 LOD2 的时候锁扣结构彻底糊成一团最后的处理是手动在建模软件里做了两级低模再导入。2. 自动 LOD 撑不住的场景手工 LOD 怎么接手2.1 自动塌陷把结构吃掉的两类典型情况前面提到了硬表面模型的问题这里再具体说两类必须人工介入的情况。第一类是薄片和细杆结构比如栏杆、天线、树枝、铁丝网。这类结构在自动简化时因为顶点密度低、拓扑细长很容易被整体压缩没掉LOD1 看上去还正常LOD2 直接消失或者变成一坨。第二类是带镂空的模型比如栅栏、窗格、齿轮自动算法会把镂空的洞填上远看变成一块实心板。这两类情况我的处理原则是轮廓优先于内部细节。手工做低模时先保证外轮廓Silhouette准确内部结构该丢就丢反正远景也看不清。比如一扇窗LOD0 有窗框、窗棂、玻璃LOD1 保留窗框和大致分格LOD2 直接做成一块带贴图的平面用贴图上的图案模拟窗棂。这样面数降得下来轮廓也不会跑偏。值得注意的是这种用贴图补几何的做法要在材质里做好配合通常需要一张带透明通道的贴图并在材质里控制好 Masked 或 Translucent 的渲染模式。如果整个场景大量使用 Masked 材质反而会增加额外的渲染开销因为 Masked 会禁用某些早期深度测试优化所以量大时要评估一下是省了面数还是亏了填充率。2.2 用外部建模工具做 LOD 再导入的完整流程手工 LOD 的标准做法是在建模软件里做好多级模型命名上体现层级然后一起导入 UE4。以常见的 FBX 导入为例命名规范大概是模型名_LOD0、模型名_LOD1、模型名_LOD2或者按网格体顺序排列。导入时 UE4 会识别 LOD 后缀自动把它们分配到各级 LOD 里比导入后在编辑器里手动加省事很多。导入之后要检查几件事。第一Lowest LOD 的 Screen Size 是不是 0 附近如果最低级 LOD 的 Screen Size 还是 0.1那当物体小到一定程度时引擎仍然会渲染它不会完全剔除。第二各级 LOD 的包围盒是否一致如果各 LOD 的包围盒差异过大切换时会出现明显的尺寸跳变也影响剔除判断。第三材质槽位是否一致LOD 之间材质槽数量不同会导致切换时材质报错。手动做 LOD 的另一个好处是可以顺带处理 UV。低模的 UV 可以重排得更紧凑贴图利用率更高甚至可以给不同的 LOD 用不同分辨率的贴图配合材质实例或贴图流送进一步省显存。这一点在做大世界的时候特别有用远景模型完全可以只挂一张 512 的贴图。2.3 导入后 LOD 不显示或者切换异常先查这几处经常有人反馈我明明导入了 LOD编辑器里切到 LOD1 却还是显示 LOD0这种问题排查起来其实有固定顺序。先看LOD Settings里的 Number of LODs 数量是否正确有时候导入后只识别了一级剩下的被当成独立网格体了。再看Source Models列表手动做 LOD 需要在这里确认每个 Source Model 对应的 LOD 索引对不对。如果数量对但显示不对检查 Screen Size 的数值是不是写反了。有一次我自己把 LOD1 的 Screen Size 设得比 LOD0 还大结果逻辑整个颠倒近处反而显示低模。UE4 要求 Screen Size 从 LOD0 到最高级 LOD 是递减的违反这个规则会触发警告。还有一种情况是平台覆盖也就是说你在编辑器里看到的可能不是目标平台的设置需要在 Static Mesh Editor 的 LOD Settings 里切换到对应平台的 Override 里检查。做移动端项目时这一点尤其重要源码版本和编辑器预览都可能和真正跑在设备上的结果有出入。3. 静态网格体合并Merge Actors 工具到底怎么用3.1 Merge 和 Proxy 是两回事别混着用打开 UE4 的 Actor 合并工具会发现面板里有一个选项区分Merge和Proxy这两个产出完全不同的东西。Merge会把选中的多个静态网格体烘焙成一个新的静态网格体资产原来的 Actor 被替换成一个普通的静态网格体它参与常规光照、可以被 LOD 系统管理、可以投射阴影。Proxy则是生成一个轻量的代理网格主要用于碰撞或者遮挡不参与正常渲染或者只作为代理使用。做性能优化时绝大多数情况你要的是 Merge。理解这个区别很重要因为有人做完 Proxy 发现场景还是原来的样子以为工具坏了。实际情况是 Proxy 只存在于物理和剔除层面视觉上并没有替换原模型。另外Merge 出来的网格体是一个整体它不能再被拆开单独移动所以合并前的取舍很关键合并的物体最好是位置上相对固定、成组出现、不需要独立逻辑的对象比如一段围墙、一组管道、堆叠的箱子而不是那些需要单独交互或移动的物件。3.2 合并前的准备UV、材质和命名三大件合并这个操作看似一键完成但结果质量好不好八成取决于合并前准备工作。UV是第一个坎。合并会把多个模型的几何拼到一个网格体里如果原来的模型 UV 有重叠比如多个箱子复用了同一套 UV合并后重叠区会打架贴图显示错乱。解决办法是合并前在建模软件里把 UV 打散不重叠或者接受合并后材质合并带来的重排。材质是第二个坎。合并工具支持材质合并它会尝试把多个材质烘焙成更少的材质用一张合并后的图集Atlas来采样。这个功能很香因为它直接减少材质数量和 Draw Call但它有上限。UE4 对合并后材质的采样器数量、贴图数量都有约束如果原来参与合并的材质种类太多、各自的贴图通道太复杂合并会失败或者产生错误。我的经验是把参与合并的材质控制在 8 种以内且尽量让它们共享同类的贴图和通道布局。命名和分组是第三个容易被忽略的点。合并出来的网格体和它替换的 Actor 最好有清晰的命名比如Wall_Seg03_Merged否则项目里很快就分不清谁是谁。有一次同事合并了三个区域命名全是默认的MergedMesh_0/1/2后面调 LOD 的时候找错对象白忙半天。3.3 合并参数面板逐项拆解合并工具的选项不多但每一项都影响结果这里按我常用的顺序梳理一遍。参数作用建议取值Merge Materials是否烘焙合并材质小物件多时开启材质复杂时关闭LOD Selection Type合并后网格体的 LOD 来源优先 Use Specific LOD 或 All LODs保证 LOD 不丢Pivot Offset合并后模型的轴心位置一般设为中心或世界原点方便摆放Generate Lightmap UVs是否重建光照贴图 UV需要烘焙光照时必开Hardshell Geometry是否保留硬边硬表面模型开启避免法线糊掉这里重点说LOD Selection Type因为这个最容易出问题。如果选错合并出来的网格体可能只带 LOD0或者干脆不带 LOD那你前面辛辛苦苦做的 LOD 就白费了。我一般会在合并后用静态网格体编辑器打开新资产确认各级 LOD 都在Screen Size 也继承过来了。Generate Lightmap UVs也值得强调合并后原来的 Lightmap UV 基本作废了如果项目用到静态光照烘焙不重建会在渲染时看到黑色的接缝或者光照错位。4. 合并之后性能到底涨在哪Draw Call 与剔除的博弈4.1 Draw Call 为什么成了移动端和 VR 的命门要理解合并的价值得先接受 Draw Call 这个概念的重量。每渲染一个网格体CPU 都要向 GPU 发一次绘制指令这个指令本身有固定开销包括状态切换、参数上传、材质绑定等等。桌面独显的 CPU 处理能力较强几千个 Draw Call 还能扛但移动端和 VR 一体机这类设备CPU 和 GPU 共享功耗预算Draw Call 数量一上去CPU 先成为瓶颈帧率会出现典型的CPU Bound——GPU 没跑满但帧就是上不去。合并静态网格体最直接的收益就是把多个 Draw Call 合成一个。一段墙由 20 个独立砖块拼成合并后变成 1 个网格体Draw Call 从 20 降到 1CPU 侧的开销骤减。同理那些场景里大量重复的小道具、装饰、碎片合并的收益非常可观。我做过一个室内的场景把书架上几十本书、桌面上的杂物合并成几组Draw Call 从 800 多降到 300 出头在移动设备上帧率直接抬了一截。但合并不是万能药它是有代价的。最大的代价是剔除粒度变粗。合并前每个小物体独立参与视锥剔除和遮挡剔除转身背对时就整个被剔除掉合并后它们成了一个整体只要包围盒有一小部分在视野里整个网格体都要被渲染哪怕你只看得到一块砖。所以合并要讲区域划分不能一锅端。4.2 合并区域怎么划分才不亏剔除这个问题的本质是合并带来 Draw Call 下降但同时带来 Overdraw 和剔除损失两者要找平衡点。我的划分原则有三条。第一条按可见性分组。经常一起出现在视野里的物体合成一组比如一面墙面上挂的装饰、一段走廊里的固定陈设。反过来门口左右两侧容易互相遮挡的东西别合并到一起。第二条控制单个合并体的面数上限。合并后的模型面数太高即使被渲染也可能因为整体太大而不划算而且单个网格体的包围盒越大剔除越不精准。移动端项目里我会把单个合并体控制在几千到一万面左右具体看预算。第三条按空间划分而非按类型划分。有人图省事把所有同类型的小物件全合并成一个比如全场景的箱子合成一个。这样做的问题是这个网格体的包围盒会覆盖整个场景视锥剔除基本失效永远在渲染。正确的做法是按房间、按区块合并让包围盒尽量紧凑。这里还要提一个和 LOD 的联动问题合并后的网格体如果自身没有 LOD或者 LOD 被合并搞丢了那远景依然会渲染它的全部面数。所以合并和 LOD 不是两件事是同一条优化链路上的两个环节顺序上一般先在单个网格体上做好 LOD再做合并合并时选对 LOD Selection Type 把各级 LOD 继承过来。4.3 合并后光照贴图和阴影的表现变化合并对光照的影响经常被低估。合并前每个小物体有自己独立的 Lightmap UV 和光照贴图空间合并后引擎需要为整个合并体重新分配光照贴图空间并重新烘焙。如果你用的是静态光照Lightmass合并后必须重新烘焙否则会出现光照不连续、明暗错位、阴影投射异常等问题。还有一个隐蔽的问题是阴影开销。合并后的大网格体投射阴影时如果场景里开了距离场阴影或者动态阴影这个大的包围盒会导致阴影计算的开销上升尤其是级联阴影CSM的划分会变得不经济。处理办法是给合并体设置合理的阴影投射距离或者对小物件直接关闭投射阴影、改用在材质里烘焙的假阴影。这属于权衡取舍需要根据场景实测来定。5. 怎么验证优化真的生效别凭感觉5.1 几个必用的性能分析工具和命令优化不能靠我觉得快了一定要有数据。UE4 里我常用的几个工具和命令目标不同配合使用。stat fps / stat unit看整体帧率和 Game、Draw、GPU、RHIT 四个时间快速判断瓶颈在 CPU 还是 GPU。stat scenerendering查看 Draw Call 数量、可见静态网格体数量、剔除统计是评估合并和 LOD 效果最直接的窗口。stat rhi看 RHI 层面的统计包括 Draw Call、三角形数量、内存占用。ProfileGPU / GPU Visualizer捕捉一帧的 GPU 时间线能定位到具体是 Base Pass、Shadow、Translucency 哪个阶段重。控制台命令 r.ForceLOD X强制所有网格体用第 X 级 LOD 渲染用来直观对比各级 LOD 的视觉效果和开销。用这些工具时要建立对比基线优化前记录一次数据合并和 LOD 处理后再记录一次对比 Draw Call、三角面数、帧率的具体变化。我习惯把几次数据记在表里方便回看是哪一步起了作用。很多时候你会发现预期省得最多的那一步实际收益一般反而是某个不起眼的批量操作效果最好。5.2 建立对比基线的具体做法做基线看起来很麻烦但做一次就受益很久。我的做法是固定一个摄像机路径或者一组测试机位保证每次测量时视角一致关闭其他无关的调试开关在同一个平台、同一套画质设置下采样。然后针对每一组改动单独记录避免多项改动混在一起说不清是谁的功劳。举个我实际操作过的例子。某个场景初始 Draw Call 约 1200三角面数约 300 万。第一步只做 LODDraw Call 基本没变因为对象数量没变但三角面数降到 180 万左右GPU 时间下降明显。第二步做合并Draw Call 降到 400 左右CPU 时间大幅下降但三角面数的降幅有限。这说明两件事解决的是不同的瓶颈LOD 主要省 GPU 的顶点和像素开销合并主要省 CPU 的绘制指令开销。搞清楚这点你就能针对项目当前卡在哪个瓶颈来优先做哪件事。这个结论其实也回答了一个常见的困惑为什么有人做完 LOD 帧率没提升有人做完合并也没感觉。原因就是他们优化的不是当前真正的瓶颈。所以在动手前先用 stat unit 判断是 CPU 还是 GPU 卡住再决定先干哪件事这个顺序特别重要。6. 我在这两件事上踩过的坑6.1 合并之后 LOD 凭空消失这个坑我踩过不止一次。现象是合并完成、双击打开新生成的网格体发现 LOD 数量只有 1前面做的三级 LOD 全没了。原因几乎都是LOD Selection Type 选错。如果选的是Use LOD0之类的选项合并时只会取最高精度的模型其他级别被丢弃。再加上被合并的多个模型本身 LOD 级数不一致合并逻辑就更难正确继承。解决办法有两个方向一是合并前统一所有参与模型的 LOD 级数二是合并时明确选择按全部 LOD来生成并在合并后逐个检查。我后来养成的习惯是合并前先写一个检查清单确认每级 LOD 都存在、Screen Size 都合法再执行合并。这多花几分钟能省掉后面几小时的返工。6.2 材质合并后贴图变成一片糊材质合并的坑也不小。有一次我把材质种类较多的一组合并了合并工具报告成功但打开一看贴图明显糊了边缘有色块。原因是合并时为了把多张贴图塞进一张图集引擎降低了分辨率或者做了有损压缩。再加上各材质的采样通道不同合并后可能丢掉了某些通道信息。处理这类问题我的经验是不要强行合并差异过大的材质。合并工具适合那种本来就同源、只是参数不同的材质比如同一个材质的不同颜色实例合并后效果几乎无损。如果是完全不同的材质体系硬合并出问题的概率很高不如保持合并网格体但保留多材质槽虽然 Draw Call 降得少一点但画质有保障。这又是一个取舍。6.3 光照贴图接缝和漏光合并后烘焙光照接缝和漏光是很常见的现象。表面原因是 Lightmap UV 重建后相邻面的 UV 在贴图上挨得太近烘焙时互相采样干扰。解决办法是调大 Lightmap 分辨率或者增大 UV 之间的间隔让各面之间有足够的空白边距。极端一点的做法是给合并体单独分配一块高分辨率的光照贴图这在小范围、对光照连续性要求高的区域是值得的。还有一种漏光不是 UV 的问题而是几何本身。合并后的网格体如果内部有面被删除或者方向反了光照会从缝隙漏进来。这时候需要检查法线朝向或者给内部填充一圈挡光几何。对于封闭的房间我一般会在合并前确认所有内部面都已经处理过避免合并后无从下手。6.4 合并体的剔除表现不如预期前文提到合并会让剔除变粗但实际表现可能比想象的更差。我遇到过一次把整层楼的固定装饰合并成一个网格体结果发现只要站在楼层任意位置这个巨大的网格体就一直在渲染剔除完全失效。后来拆成按房间分组的四个合并体帧率立刻好转。这个教训是合并体的包围盒尺寸是决定剔除效率的关键宁可多合并几个小体也不要贪图 Draw Call 数字而合并成一个巨无霸。判断标准可以简单粗暴一点合并体的包围盒如果有相当一部分会长期不在视野内那这个合并就是划算的如果它的包围盒几乎覆盖了玩家的整个活动范围那它永远在渲染合并带来的收益会被剔除损失抵消甚至反超。6.5 一次典型的完整排查过程最后把一次比较完整的排查经历讲一下方便对照复现。当时某个室内场景在移动设备上掉帧严重我按下面的顺序走了一遍。第一步用stat unit确认帧率瓶颈发现 Game 时间偏高Draw Call 是关键线索。第二步用stat scenerendering看可见静态网格体数量和 Draw Call数字接近一千明显超预算。第三步检查场景中的重复小物件发现大量装饰、书本、餐具都是独立 Actor没有任何合并。第四步把这批小物件按房间分组先做 LOD部分硬表面手动做再用合并工具合成几个区域性的网格体合并时确认 LOD 继承和 Lightmap UV 重建。第五步重新在设备上测量Draw Call 降到三百多帧率回到目标值。第六步回看画面确认没有明显的糊边、接缝和阴影异常优化完成。这次经历让我更加确信一点LOD 和合并是性能优化的基础功不是可选项。它们不像某些高级渲染特性那样炫目但在一线项目里把这两件事做扎实往往比堆各种花哨效果更能稳住性能底线。而且它们的概念并不复杂难的是养成摆场景的同时就在想 LOD 和合批的习惯以及愿意花时间做测量和对比而不是凭感觉。后续再遇到性能问题我一般会优先回看这两个环节有没有落实多数情况下答案就在这里。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑