UE5.8 渲染调试与可视化:让性能瓶颈无所遁形
引子:阿杰的周五下午
周五下午五点,阿杰的性能优化报告还没写完。策划反馈某个森林关卡掉帧严重,阿杰打开场景,树、草、石头、水面看着都正常。他凭经验关了动态阴影,帧率没变;降低了后期处理质量,帧率也没变;把远处树木的 LOD 调低,帧率反而更差了。
正当他准备复制粘贴「需要进一步排查」到邮件里时,组里的老同事丢过来一句话:「打开 Shader Complexity 视图看看。」
三分钟后,阿杰发现一片草丛的 shader 是血红色的。原来美术为了做风吹效果,在草丛材质里塞了世界位置偏移、多个纹理采样和复杂噪声。整个屏幕超过三分之一的像素都在跑这个 shader。
这就是渲染调试工具的价值:它把看不见的成本变成看得见的颜色。
一、为什么需要专门的渲染调试工具
性能优化最怕的不是问题难,而是找不到问题在哪。渲染管线涉及 CPU、GPU、内存、带宽多个层面,瓶颈可能藏在:
- 某个材质的 shader 指令数爆炸;
- 某盏灯的照射范围重叠了十几盏其他灯;
- 某个模型的 LOD 切换距离设置错误;
- 某块区域的 overdraw 严重;
- 纹理流送跟不上导致模糊或尖峰。
没有可视化工具,这些只能靠猜。UE5.8 提供了一整套视图和命令,把渲染内部状态暴露出来。
flowchart TD
A[性能问题] --> B{用哪个工具看}
B -->|CPU 瓶颈| C[stat unit / stat game]
B -->|GPU 瓶颈| D[stat gpu / GPU Visualizer]
B -->|材质问题| E[Shader Complexity]
B -->|灯光问题| F[Light Complexity]
B -->|几何问题| G[LOD Coloration / Nanite Viz]
B -->|填充率问题| H[Quad Overdraw]二、Stat 命令:最快速的全局快照
stat 系列命令是 UE 最老也最可靠的性能分析入口。在编辑器或运行时按 ` 打开控制台,输入即可。
2.1 最常用的一组命令
stat unit # 显示 Frame / Game / Draw / GPU / RHIT 时间
stat fps # 显示帧率
stat gpu # 显示 GPU 各阶段耗时
stat rhi # 显示 RHI 层统计,包括 draw call、三角形数
stat scenerendering # 显示场景渲染相关统计
stat nanite # 显示 Nanite 统计
stat lumen # 显示 Lumen 统计
stat memory # 显示内存概览2.2 怎么读 stat unit
stat unit 会显示五行时间:
- Frame:完整一帧的时间;
- Game:游戏逻辑线程时间;
- Draw:渲染准备线程时间;
- GPU:GPU 实际渲染时间;
- RHIT:渲染硬件接口线程时间。
如果 Frame 接近 GPU,说明瓶颈在 GPU;如果 Frame 接近 Game,说明瓶颈在游戏逻辑;如果 Draw 很高,说明 CPU 端提交 draw call 或 culling 有压力。
sequenceDiagram
participant G as Game Thread
participant D as Draw Thread
participant R as RHI Thread
participant GPU as GPU
G->>D: 更新场景/提交绘制
D->>R: 构建渲染命令
R->>GPU: 提交命令缓冲
GPU-->>R: 完成渲染2.3 一个简单的数学视角
假设目标帧率是 60fps,那么每帧可用的总时间为:
如果 stat unit 显示 GPU 耗时 14ms,留给 Game 和 Draw 的时间只剩不到 2.7ms。对于开放世界或复杂物理模拟,这非常紧张。
2.4 stat unit 各行的具体解读
阿杰第一次调出 stat unit,屏幕上跳出几行白字,他盯着 Frame 后面的数字发呆。老周走过来,用鼠标指了指:「Frame 是总账,单看它没用,要看它跟下面哪一行对齐。如果 Frame 跟 GPU 贴得很近,瓶颈就在显卡;如果 Frame 追着 Game 跑,就是逻辑线程在拖后腿;如果 Draw 比 Game 还高,多半是场景剔除或提交 draw call 太慢。」
Frame 行给出完整一帧的耗时。目标 60fps 时,它必须低于 16.67ms;目标 30fps 时,低于 33.33ms。超出的部分就是我们要抠掉的毫秒数。
Game 行反映游戏逻辑线程。它负责 Actor Tick、动画蓝图、物理模拟、AI 行为树、蓝图事件等。这行数值高时,常见原因是太多 Tick 开启的 Actor、每帧都跑的复杂碰撞检测、没有 Sleeping 的物理物体,以及事件图表里的大循环。
Draw 行反映渲染准备线程。UE5 把场景遍历、视锥剔除、遮挡剔除、阴影投射物收集、渲染状态排序都放在这里。场景中静态网格数量过万、动态阴影数量多、HLOD 生成不合理,都会让 Draw 时间爬升。阿杰曾遇到一个关卡 Draw 跑到 25ms,GPU 却只有 8ms,最后发现是某个蓝图每帧都在动态生成大量粒子系统,导致剔除列表爆炸。
GPU 行是 GPU 实际用于着色和光栅化的时间。BasePass、ShadowDepths、PostProcessing、Lumen、Translucency 都会算进这里。如果 GPU 高,下一步就进 GPU Visualizer 拆开看。
RHIT 行是渲染硬件接口线程,也就是把渲染命令提交给显卡驱动的时间。Draw call 数量越多、状态切换越频繁、资源屏障越复杂,RHIT 就越高。有时 GPU 不高但 RHIT 高,说明 CPU 在驱动层被卡住了,降低 draw call 或减少动态纹理上传会更有效。
判断逻辑可以总结为:先看 Frame 是否超过目标帧率;再看 Frame 贴近哪一行;然后针对贴近的那一行深入。多线程项目中,Frame 往往由最慢的那个线程决定,其它线程可能在等它。
下面是一段 stat unit 的典型输出,以及几个可以配合使用的命令:
# 典型 stat unit 输出(数值仅为示例)
Frame: 22.4 ms
Game: 8.2 ms
Draw: 18.7 ms
GPU: 20.1 ms
RHIT: 19.5 ms
# 把数字变成实时折线图
stat unitgraph
stat fps2.5 老周的判断流程
老周在白板上画了四条线:「你把它当成体检报告。Frame 是身高体重,Game、Draw、GPU、RHIT 是血压、血糖、血脂。哪项超标治哪项。」
阿杰照着这个思路,给项目定了一套快速判断规则:
- Frame 超过 16.67ms 且贴近 GPU → 进 GPU Visualizer,查 BasePass、Shadow、Lumen;
- Frame 超过 16.67ms 且贴近 Game → 开
stat game看 Tick、物理、动画; - Frame 超过 16.67ms 且贴近 Draw → 看场景中 mesh 数量、动态阴影数量、遮挡剔除结果;
- GPU 和 RHIT 同时高 → 同时降 draw call 和材质复杂度;
- GPU 不高但 Frame 高 → 检查同步、垂直同步、线程等待。
这套规则不一定能定位到具体材质,但能快速排除一半以上的方向。
三、GPU Visualizer:GPU 时间的解剖刀
stat gpu 给你一个总览,但想知道具体哪个 pass 花了多少时间,要用 GPU Visualizer。快捷键通常是 Ctrl + Shift + ,,或者在控制台输入 profilegpu。
3.1 界面解读
GPU Visualizer 会列出当前帧所有 GPU pass,比如:
- BasePass
- Lighting
- ShadowDepths
- PostProcessing
- Lumen
- Virtual Shadow Maps
- Translucency
每个 pass 后面跟着耗时。点击可以展开子项。
3.2 一个实战案例
阿杰打开 GPU Visualizer 后,发现 ShadowDepths 占了 4.5ms。展开后发现是一个方向光的级联阴影在消耗。进一步看,第三、四级联分辨率过高,而远处物体又不够多。他把 r.Shadow.CSM.MaxCascades 从 4 降到 3,远处改用 VSM,ShadowDepths 降到 1.8ms。
flowchart LR
A[GPU Visualizer 发现 ShadowDepths 高] --> B[展开看级联分布]
B --> C[降低级联数]
C --> D[远处改用 VSM]
D --> E[帧率提升]3.3 常见 pass 的典型耗时范围
老周带过几个项目,对常见 pass 的耗时心里有杆秤。BasePass 在普通场景中大约 2 到 4ms;复杂开放世界或植被密集场景会到 5 到 7ms;超过 8ms 就要怀疑材质复杂度过高或 overdraw 严重。ShadowDepths 对方向光来说通常在 1 到 3ms,如果用了 4 级联且分辨率高,可能冲到 4ms 以上。点光源和聚光灯的阴影便宜一些,但数量多了也会累加。
PostProcessing 这个 pass 一般 0.5 到 2ms,Bloom、SSAO、Motion Blur、Depth of Field、Lens Flare 都在里面。后期总耗时超过 3ms 时,可以逐项关闭排查。Lumen 在小型室内场景约 2ms,复杂室外场景可能 4 到 6ms;如果看到 Lumen pass 里 Surface Cache 更新占了大头,说明场景里细小物体太多,距离场采样不够稳定。
Virtual Shadow Maps 通常 1 到 3ms,但缓存失效时会突然尖峰。Translucency 的正常范围是 0.5 到 2ms,粒子系统大量叠加时轻松破 5ms。阿杰的森林关卡里,Translucency 一度 6ms,GPU Visualizer 展开后发现是十几层透明落叶粒子叠在一起。
这些数字不是死线,而是参考。不同硬件、不同分辨率、不同项目设置都会有偏差。关键是抓到自己的基线,然后在异常时对比。
打开 GPU Visualizer 的常用命令如下:
profilegpu # 捕获并打开 GPU Visualizer
Ctrl + Shift + , # 编辑器默认快捷键
r.ProfileGPU.Sort Order 0 # 按耗时排序四、Shader Complexity:材质的照妖镜
Shader Complexity 视图把屏幕按 shader 指令数着色。绿色表示便宜,红色表示贵,白色表示极其昂贵。
4.1 常见红色区域
- 复杂的水面 shader;
- 多层混合的地形材质;
- 带大量 world position offset 的植被;
- 滥用
if分支和复杂噪声的材质; - 透明或半透明叠加区域。
4.2 Quad Overdraw
Quad Overdraw 视图显示同一个 2x2 像素块被重复绘制的次数。透明粒子、重叠植被、大量 UI 元素是重灾区。
这两个视图通常一起用。Shader Complexity 告诉你「哪里 shader 贵」,Quad Overdraw 告诉你「哪里像素被重复画太多次」。
graph TD
A[画面卡顿] --> B[Shader Complexity 视图]
A --> C[Quad Overdraw 视图]
B --> D[红色区域 = 材质复杂]
C --> E[红色区域 = 过度绘制]
D --> F[简化材质]
E --> G[减少透明叠加]4.3 用公式理解渲染开销
单帧像素着色开销可以近似表示为:
其中 是像素数, 是该像素被覆盖的次数(overdraw), 是 shader 指令数。Quad Overdraw 控制 ,Shader Complexity 控制 。两者同时高时,开销会指数级上升。
4.4 白色区域的危险阈值
Shader Complexity 视图里,白色比红色更危险。绿色通常代表每个像素几十条指令,黄色过百,红色接近两百,白色往往超过三百甚至五百。在 1080p 分辨率下,白色区域只要占到屏幕中心 5% 以上,就可能吃掉 2 到 4ms 的 GPU 时间。在移动平台,白色阈值更低,超过六十条指令的 shader 就已经需要警惕。
阿杰看完森林关卡后,把白色区域截图发给了美术。美术一开始不服气:「草丛不就加点风动噪声?」老周把 GPU Visualizer 截图甩过去:「这个草丛的 pixel shader 占了 BasePass 三分之一,屏幕里还有几千棵。」
白色区域的处理优先级最高。做法分几步:把 world position offset 里的噪声节点换成更简单的正弦组合;减少纹理采样次数,把四层混合压到两层;用 static switch 把只在高端平台才用的功能关掉;把可以在顶点阶段完成的计算从 pixel shader 搬到 vertex shader。
viewmode shadercomplexity
viewmode shadercomplexitywithdrawn # 包含被遮挡区域
r.ShaderComplexity.MaxPixelShaderInstructionsToDraw 5004.5 优化复杂材质的实操顺序
老周建议阿杰按这个顺序动手,不要同时改太多地方,否则不知道是哪里起效:
- 打开 Shader Complexity,截一张全屏图;
- 把白色和红色区域对应到具体材质;
- 对每个材质,用 Material Editor 的 Stats 面板看指令数;
- 优先砍掉透明度和世界位置偏移里的复杂节点;
- 改完后重新进 Shader Complexity 对比;
- 如果 Quad Overdraw 也红,再减少透明叠加。
阿杰按照这个顺序,只用两天就把森林关卡的 BasePass 从 7ms 降到 4ms。
五、Light Complexity:灯光重叠的警报器
Light Complexity 视图用颜色显示一个像素被多少盏灯影响。蓝色表示少,白色表示多到离谱。
5.1 为什么重要
每盏动态光都会增加该像素的光照计算。如果一个区域同时被 8 盏点光源影响,即使每盏灯本身很便宜,加起来也贵得惊人。
5.2 优化策略
- 缩小点光源的衰减半径;
- 移除不影响视觉的小灯;
- 用自发光材质代替微弱装饰灯;
- 把重叠的灯光合并或减少。
老周团队做过一个酒吧场景,天花板上挂了四十多盏小射灯。Light Complexity 视图一片白。他们把大部分射灯改成自发光贴图,只保留几盏真正影响角色的动态光,帧率从 38 回到 60。
architecture-beta
group ue_engine="UE5.8 Engine"
service viewmode:viewmode{"Light Complexity View"} in ue_engine
service basepass:basepass{"Base Pass"} in ue_engine
service lighting:lighting{"Lighting Pass"} in ue_engine
service output:output{"Screen Color"} in ue_engine
viewmode:B --> basepass:T
basepass:B --> lighting:T
lighting:B --> output:T5.3 动态光数量与性能的关系
Light Complexity 用颜色表示每个像素受多少盏动态光影响。蓝色和绿色代表 1 到 2 盏,黄色 3 到 4 盏,橙色 5 到 7 盏,红色 8 盏以上,白色则意味着十几盏灯叠在一起。桌面端 deferred shading 可以承受一定数量的重叠,但超过 4 盏动态光同时照射同一区域,开销就会明显爬坡;超过 8 盏,基本稳不住 60fps。
动态光数量与性能不是线性关系。第一盏带阴影的方向光最贵,后面每盏点光源都会重复计算光照和阴影。老周的经验是:主要角色照明用 1 到 2 盏动态光,环境装饰灯尽量用静态烘焙或自发光贴图,玩家经过时才会触发的小灯用触发器控制开启。阿杰把酒吧天花板的四十多盏小射灯关掉后,Light Complexity 视图从白变蓝,帧率回到了 60。
viewmode lightcomplexity
ShowFlag.DynamicShadows 0 # 临时关闭动态阴影对比帧率
r.LightMaxDrawSphereCount 0 # 调试时禁用灯光剔除球六、LOD Coloration 与 HLOD Coloration:检查模型退化
6.1 Mesh LOD Coloration
这个视图用不同颜色显示每个物体当前使用的 LOD 级别。理想情况下,近处是 LOD0,远处逐渐变成 LOD1、LOD2。
如果近处物体显示成 LOD1 或 LOD2,说明 LOD 切换距离太近,细节丢失。如果远处物体一直是 LOD0,说明 LOD 没生效,浪费性能。
6.2 HLOD Coloration
HLOD Coloration 显示哪些物体被合并到 HLOD 集群里。开放世界项目用这个视图检查 HLOD 生成是否合理。
flowchart LR
A[打开 LOD Coloration] --> B{近处是什么颜色}
B -->|LOD0| C[正常]
B -->|LOD1/2| D[切换距离太近]
A --> E{远处是什么颜色}
E -->|LOD2+| F[正常]
E -->|LOD0| G[LOD 未生效]七、Nanite 与 Lumen 的专用视图
7.1 Nanite 可视化
r.Nanite.Visualize 1 # 基础可视化
r.Nanite.Visualize 2 # Cluster 分布
r.Nanite.Visualize 3 # Triangle 密度
r.Nanite.Visualize 4 # Material 复杂度这些视图帮你判断 Nanite 网格是否过于密集、cluster 分布是否合理、材质是否太复杂。
7.2 Lumen 可视化
Show > Visualize > Lumen Overview
Show > Visualize > Lumen Scene
Show > Visualize > Mesh Distance Fields
r.Lumen.Visualize.CardPlacement 1
r.Lumen.Visualize.SurfaceCache 1排查 Lumen 漏光、自发光不亮、间接光缺失时,这些视图是必备工具。
7.3 Nanite 可视化模式的实战用法
Nanite 可视化不是只看热闹。r.Nanite.Visualize 1 是总览,能快速确认哪些物体真正走了 Nanite 管线;如果预期是 Nanite 的岩石还是传统网格,说明导入设置或 Nanite 支持开关没开。
r.Nanite.Visualize 2 看 cluster 分布。Cluster 是 Nanite 的渲染单元,颜色越密集代表 cluster 越碎。镜头附近出现大量细小 cluster,往往意味着三角形过密,可以把 r.Nanite.MaxPixelsPerEdge 从默认 1.0 稍微调大,或用 Nanite 的 proxy triangle percentage 减少细节。
r.Nanite.Visualize 3 看 triangle 密度。理想情况下每像素对应 1 到 2 个三角形;如果某块区域亮到发白,说明 tessellation 过度。阿杰的山体模型在这个模式下中间白、边缘蓝,他把源模型的面数降了 30%,画面看不出区别,帧率却涨了 4fps。
r.Nanite.Visualize 4 看 material 复杂度。它按材质 ID 着色,同一个 cluster 里材质种类越多,raster bin 开销越高。颜色花得像打翻调色盘的区域,要把材质合并或减少材质数量。
配合 stat nanite 看 cluster 总数、剔除率和三角形数,判断优化有没有效果。
r.Nanite.Visualize 3
stat nanite
r.Nanite.MaxPixelsPerEdge 1.0 # 默认值,减小以降低三角形密度
r.Nanite.MaxClusterPixels 64八、Texture Streaming 与内存视图
8.1 Required Texture Resolution
这个视图对比「当前加载的纹理分辨率」和「GPU 实际想要的分辨率」。如果大量区域显示红色,说明纹理流送跟不上,画面会模糊。
8.2 Lightmap Density
显示 lightmap 纹素密度。蓝色表示稀疏,红色表示过密。对于还在用 baked lighting 的项目,这个视图帮助优化 lightmap UV 和分辨率。
8.3 Stat Memory 与 Texture Memory
stat memory
stat streaming
stat rhi这些命令显示纹理池使用、池大小、未满足的请求数。如果 Texture Streaming Pool 经常溢出,需要增大池大小或降低纹理分辨率。
8.4 Texture Streaming Pool 溢出排查
Texture Streaming Pool 溢出在游戏里表现为贴图模糊、远处物体细节突然弹出、stat streaming 里 Pool 使用接近 100%。r.Streaming.PoolSize 默认根据显存自动设置,但项目里大量 4K 贴图会把池子撑爆。
阿杰排查过一起这样的 bug:角色靠近一面石墙,墙面突然变糊。他打开 Required Texture Resolution 视图,满屏红色;stat streaming 显示 Pool 用了 98%。他在 Content Browser 里按纹理大小排序,发现有几块石墙纹理 4K 且没有启用压缩,还有几张贴图被重复导入。把石墙降到 2K、删除重复资源、给远处物体设置 LOD bias 后,Pool 降到 75%,红色区域消失。
排查流程:先运行 stat streaming 看 Pool Size、Pool Used、Over Budget;再看 Required Texture Resolution 视图是否大面积飘红;然后在 Content Browser 中筛选 Texture,按资源大小排序,找出 oversized 资产;最后用 r.Streaming.MipBias 临时提高 mip 偏移,验证模糊是否由 pool 不足引起。
stat streaming
r.Streaming.PoolSize 2048
r.Streaming.FramesForFullUpdate 30
r.Streaming.MipBias 1九、RenderDoc / PIX:帧级手术刀
当内置工具还不够时,就要上外部帧分析工具。
9.1 RenderDoc
RenderDoc 可以捕获一帧,查看每个 draw call、每个渲染目标、每个纹理和 shader。适合排查:
- 特定物体为什么那么贵;
- 渲染目标是否被错误清除;
- Shader 编译结果是否符合预期。
9.2 PIX
PIX 是微软的 GPU 调试工具,对 DirectX 12 项目支持更好。除了 RenderDoc 的功能,还能做 GPU 时间线分析和内存快照。
sequenceDiagram
participant D as 开发者
participant R as RenderDoc/PIX
participant G as GPU
D->>R: 捕获一帧
R->>G: 重放命令
G-->>R: 返回每个 pass 的耗时与资源
R-->>D: 可视化展示9.3 RenderDoc 捕获 UE5 帧的具体步骤
RenderDoc 捕获 UE5 帧有几种方式。最简单的是安装 UE 自带的 RenderDoc 插件:在 Plugins 窗口搜索 RenderDoc,启用后重启编辑器。进入关卡,按 F12 即可捕获当前帧,Capture 文件会保存在项目 Saved 目录下。
如果需要在打包版本或特定启动参数下捕获,可以从 RenderDoc 主界面 Launch Application。选择 UnrealEditor.exe 或可执行文件,Working Directory 设为项目目录,Command-line Arguments 填入项目 uprpoject 路径,例如 D:\Project\MyProject\MyProject.uproject。勾选「Queue Capture of Frame(s)」并设好帧号,启动后 RenderDoc 会自动抓取。
捕获完成后,在 RenderDoc 的 Event Browser 里按耗时排序,找到最重的 draw call。点击后看 Pipeline State,检查 Vertex Shader 和 Pixel Shader 的指令数;打开 Texture Viewer 看输入纹理是否过大;用 Mesh Viewer 检查顶点数是否异常;在 Pixel History 里看某个像素被绘制了多少次,从而确认 overdraw。
# 通过 RenderDoc 启动 UE5 编辑器
renderdoccmd.exe capture --opt-hook-children ^
--working-dir D:\UE5Editor ^
D:\UE5\Engine\Binaries\Win64\UnrealEditor.exe ^
D:\Project\MyProject\MyProject.uproject9.4 在 RenderDoc 里看什么
在 RenderDoc 里看 UE5 帧,要习惯它庞大的命令列表。不要逐行看,先按 GPU Duration 排序,把注意力放在耗时 top 10 的事件上。BasePass 和 ShadowDepths 通常会占据前排。
看到某个 draw call 异常沉重时,先确认它对应的 mesh:在 Mesh Viewer 里看顶点数和索引数,再切到 Texture Viewer 看用到的纹理分辨率。Pixel Shader 如果有大量纹理采样或分支,编译后的 DXIL 行数会很长。对比相邻 draw call,很容易找出是模型面数过高、材质太复杂,还是 overdraw 严重。
如果捕获的是 D3D12,还要注意资源屏障和同步开销。RenderDoc 的 Statistics 窗口会列出每个 pass 的 PS invocations 和 vertex count,这两个数字能快速量化填充率压力。
十、UE5.8 新增与改进的调试能力
UE5.8 在调试方面也有一些改进:
- MegaLights 调试工具:Light Finder 和 Ray Visualizer;
- 改进的 Nanite 统计:更详细的 cluster 和 raster bin 信息;
- Lumen 可视化增强:更好的 Surface Cache 覆盖显示;
- 新的 Gizmo 系统:虽然不属于渲染调试,但让场景调整更精确,减少因误操作导致的性能问题。
十一、一份最小可行调试流程
遇到渲染性能问题时,可以按这个顺序排查:
stat unit看瓶颈在 CPU 还是 GPU;- 瓶颈在 GPU,打开 GPU Visualizer 定位具体 pass;
- 怀疑材质,开 Shader Complexity 和 Quad Overdraw;
- 怀疑灯光,开 Light Complexity;
- 怀疑几何,开 LOD Coloration 和 Nanite 可视化;
- 怀疑纹理,开 Required Texture Resolution 和
stat streaming; - 还找不到,用 RenderDoc 或 PIX 抓帧。
flowchart TD
A[性能问题] --> B[stat unit]
B --> C{瓶颈位置}
C -->|GPU| D[GPU Visualizer]
D --> E{哪个 pass}
E -->|BasePass| F[Shader Complexity]
E -->|Shadow| G[Shadow/VSM 设置]
E -->|Lumen| H[Lumen 可视化]
C -->|CPU| I[stat game / draw]
F --> J[优化材质]
G --> K[优化阴影]
H --> L[调 Lumen 参数]
I --> M[优化逻辑或 culling]十二、写在最后
渲染调试不是炫技,是省钱。阿杰那个周五下午,如果没有 Shader Complexity 视图,他可能会把全场景的阴影、后期、LOD 都改一遍,最后发现方向完全错了。
好的调试工具让你一次只看一个问题。颜色越红的地方,越值得花时间。掌握这些视图和命令,你就能在美术和策划改需求时,迅速判断改动对性能的影响。
性能优化本质上是一场对话:你提出假设,工具给出证据,你再调整。没有证据的优化,通常只是在碰运气。