性能优化系列 · 设置篇。一句话摘要:移动端不要一套 URP 配置跑到底,先按高中低设备分档,再决定 HDR、阴影、后处理这些开关在哪些档位保留。每个设置先看官方三档,再弄清它做什么、性能消耗在哪里、关掉画面会不会差;项目没用到、或者中低端吃紧,就按档位牺牲掉。
移动端做 URP 设置,第一件事不是问「这个开关到底该不该开」,而是先问「它该在哪一档设备上开」。高端机可以保留更多画面层次,中端机保留最容易被玩家感知的效果,低端机优先守住帧率、温度和内存。比如 HDR:如果项目强依赖 Bloom、Tonemapping,高端机可以开;中端机要看真机带宽和后处理耗时;低端机如果没有明显画面收益,直接关掉通常更稳。
这也是后面所有建议的前提:不是把画质开关简单分成开和关,而是把它们接到设备档位上。同一个开关在高端机上可能是画面收益,在低端机上可能就是发热、掉帧和全屏带宽。
以默认 URP 工程为例
这篇对着 Unity 2022.3 自带的 URP 模板讲。模板里有三档 Pipeline Asset,Quality 里各绑一份:
URP-Performant→ PerformantURP-Balanced→ BalancedURP-HighFidelity→ High Fidelity
设置散在三处,官方也是三处一起切:
- URP Asset:阴影、附加光、HDR、MSAA、Render Scale、全屏纹理
- Renderer Asset:Renderer Feature、后处理数据
- Quality Settings :
lodBias、蒙皮权重、各向异性,以及这一档用哪份 Pipeline Asset
这套配置不是「只给手机」或「只给 PC」。Quality 里的平台默认档把意图写死了:Android / iPhone / tvOS / WebGL 默认 Balanced ;Standalone 和主机默认 High Fidelity;Server 才是 Performant。
这篇文章以官方 URP 的三个档位作为参考坐标。移动端不要直接照搬官方的 High Fidelity,也不要一上来就压到 Performant;更合理的做法是:先理解官方 Performant / Balanced / High Fidelity 的差异,再以官方 Balanced 作为移动端基础配置,在这个基础上拆出移动端高 / 中 / 低三档。
移动端高档可以保留更多接近 Balanced 的效果;移动端中档以 Balanced 为基线逐项 A/B;移动端低档则向 Performant 收,把项目没用到、或者成本明显高于收益的项关掉。High Fidelity 上的 4096 阴影、4 级级联、MSAA 4x、每对象 8 盏附加光,主要面向 PC / 主机,不应该直接搬到手机上。
后面每一项都按同一套格式讲:官方三档、它是干什么的、性能消耗和画面差、建议。性能消耗是低 / 中 / 高;画面差是轻微 / 中等 / 明显。口径来自 URP 手册标的「性能影响」、Unity 对效果本身的定义,以及移动端常见压测经验。
HDR
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 开 | 开 |
HDR 是让颜色缓冲能记下更亮和更暗的值,而不是把高光直接裁成纯白。开了以后,Bloom、Tonemapping、基于物理的光照才有足够的亮度范围可算;关掉时,颜色写在普通 LDR 缓冲里,带宽更省,但亮部更容易过曝、Bloom 也更容易脏。
| 性能消耗 | 画面差 |
|---|---|
| 中 | 中等 |
消耗性能的地方在于更大的颜色 RT,以及后续依赖 HDR 的全屏后处理。没有 Bloom、也看不出色带,关了几乎没人察觉。模板 Graphics 里 Lights Use Linear Intensity 默认是开的,和 HDR 配套;只开 HDR、线性强度却关着,画面会「亮了但也不对」。
建议:项目没有 Bloom、Tonemapping,或者中低端带宽已经吃紧,可以关。反过来,如果决定开启 HDR,就不要只孤立地勾 HDR:颜色空间建议使用 Linear,Lights Use Linear Intensity 也要保持开启;Bloom、Tonemapping 这类依赖高动态范围的后处理,再按画面需求和设备档位一起评估。少开其中一环,常见结果是性能成本付了,亮度和高光却不稳定。
MSAA
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 关 | 4x |
MSAA 是多重采样抗锯齿:在三角边缘多采几个点,把锯齿抹平。它管的是几何边缘,不是贴图模糊,对 UI 图、文字几乎没帮助。
| 性能消耗 | 画面差 |
|---|---|
| 高 | 中等 |
Unity 手册写明 MSAA 会用带宽在 framebuffer 上来回拷。手机 GPU 是 tile-based,倍数直接打在每个像素上。URP Asset 和 Quality 里的 Anti Aliasing 会一起生效,两处都开等于叠了一次。画面上只有 3D 模型边缘会锯;纯 UI、卡片、偏平的场景,开不开差不多。
建议:如果模型几何边缘锯齿明显,并且目标设备仍有足够的带宽和帧时间余量,最多尝试 2x,并和 Render Scale 一起评估。先降低 Render Scale 再开启 MSAA,往往会让画面更糊,收益不一定成立。中低端设备不建议开启,更不要直接套用 4x。
主光阴影
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 开,1024 | 开,4096 |
主光阴影是平行光(太阳光)打出来的实时阴影:先把场景从灯光方向画进一张 shadowmap,再在物体上采样,决定这块是不是在影子里。没有它,角色和建筑不会在地上投下随时间动的影子;有它,远近层次会清楚很多。
| 性能消耗 | 画面差 |
|---|---|
| 高 | 明显 |
多一张 shadowmap、多一个阴影 Pass,手机还要付采样带宽。分辨率从 1024 拉到 4096,图是 16 倍面积。没有角色在地上走、没有会动的接触阴影,关了几乎看不出;有角色、有建筑落影,一关就扁。
建议:如果场景里没有需要随物体移动的实时阴影,或者中低端设备的 Shadows、SetPass、带宽已经吃紧,可以关闭主光实时阴影,改用烘焙阴影或贴片阴影。不要为了「更清晰」直接把阴影分辨率拉到 4096。
附加光
| Performant | Balanced | High Fidelity |
|---|---|---|
| Disabled | Per Pixel,每对象 2 | Per Pixel,每对象 8 |
附加光是主光之外的点光、聚光。Disabled 完全不算;Per Vertex 在顶点上算,便宜但大面体会有色块;Per Pixel 在每个像素上算,体积光、近处灯更准,CPU 要按物体循环灯光,片元也更贵。每对象上限决定同一个物体最多吃几盏。
| 性能消耗 | 画面差 |
|---|---|
| 中~高 | 中等 |
Per Pixel 是 CPU + GPU 两边账单。场景里根本没有点光 / 聚光,这项等于白开循环;只有主光的大厅、卡牌桌,关了没画面差。
建议:如果场景里没有点光 / 聚光,或者中低端设备的渲染提交已经吃紧,可以降到 Per Vertex 或 Disabled。不要直接套用每对象 8 盏的上限,先确认同一个物体实际最多会受到几盏灯影响。
附加光阴影
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 关 | 开,4096 |
附加光阴影让点光、聚光也能投影子,例如手电筒打在墙上的光斑边缘。每开一盏,就要再出一份阴影图。
| 性能消耗 | 画面差 |
|---|---|
| 高 | 中等 |
Unity 自己的性能建议也是:用得着附加光时,先降 atlas,能关阴影就关。没有手电筒、局部灯打墙,开了也看不见。
建议:角色脚下的局部阴影、手电筒一类效果优先考虑 Blob Shadow 或贴片方案。不要只为了一盏附加光,就启用 High Fidelity 那套附加光阴影。
阴影距离
| Performant | Balanced | High Fidelity |
|---|---|---|
| 50 | 50 | 150 |
阴影距离是实时阴影从摄像机出发能盖多远。超出这段的物体不再进 shadowmap,远处就没有实时影子。距离越大,同一张图要覆盖的世界越大,近处影子越糊,除非再加级联或提高分辨率。
| 性能消耗 | 画面差 |
|---|---|
| 中 | 中等 |
距离拉长,阴影 Pass 里的物体变多。摄像机永远对着近处桌面,50 米以外的影子本来就没有观众。
建议:如果摄像机视距很近、远处阴影没有实际观感收益,或者中低端设备上的 shadowmap 已经变糊且带宽压力明显,可以进一步缩短阴影距离。移动端不要直接拉到 150。
阴影级联
| Performant | Balanced | High Fidelity |
|---|---|---|
| 1 | 1 | 4 |
级联是把阴影距离切成几段,近处一张高精度 shadowmap,远处一张低精度。1 级就是整段共用一张图;4 级是近处很细、远处四份图轮着画。级联越多,近处影子越利,Pass 和带宽也越多。
| 性能消耗 | 画面差 |
|---|---|
| 高(4 级) | 中等 |
Unity 手册写明增加 cascade 会减性能。近处没有角色脚底影子,1 级和 4 级看不出差别。
建议:不要上 4 级联。
软阴影
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 开 | 开 |
软阴影是在已经有实时阴影之后,对影子边缘做滤波,让边缘不那么硬。它不产生影子,只改影子的样子。
| 性能消耗 | 画面差 |
|---|---|
| 高 | 中等 |
URP 手册把这项标成性能影响:高。关掉就回退成硬件滤一次。主光阴影都关了,这项零画面、只留变体。
建议:如果主光阴影已经关闭,软阴影也应该一起关闭;如果中低端设备上软阴影滤波的收益不足,也可以关闭。
Render Scale
| Performant | Balanced | High Fidelity |
|---|---|---|
| 1 | 1 | 1 |
Render Scale 是 3D 场景相对屏幕的渲染分辨率。1 是按屏幕像素画;0.8 是先画小一点再拉伸。它只管填充,不管阴影 Pass、附加光循环这些 CPU 侧提交。UI 仍按设备分辨率画。
| 性能消耗 | 画面差 |
|---|---|
| 高(填充) | 一关就明显(3D 会糊) |
下调对 GPU fill 很有效,3D 会立刻软一档,UI 不受影响。不要当唯一手段,降了分辨率,阴影和附加光该贵还是贵。
建议:如果中低端设备的 GPU 填充压力已经很高,并且项目能接受 3D 画面略微变糊,可以下调 Render Scale。
Depth Texture
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 关 | 关 |
Depth Texture 是把相机深度再拷一份出来,给软粒子、折射、SSAO、某些后处理采样「这一点离相机多远」。开了就是一张常驻全屏图加一次拷贝。
| 性能消耗 | 画面差 |
|---|---|
| 中 | 几乎看不出(没人采样则无差) |
Unity 的性能清单把「用不到就关 Depth Texture」写在最前面。没有软粒子、SSAO、深度特效,开着是纯带宽。
建议:没有明确使用者就关。效果砍了开关一起关。
Opaque Texture
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 关 | 关 |
Opaque Texture 是不透明物体画完后的场景颜色拷贝,给折射、一些扭曲特效去采样「后面是什么」。同样是全屏拷贝 + 常驻显存。
| 性能消耗 | 画面差 |
|---|---|
| 中 | 几乎看不出(没折射 / 扭曲则无差) |
和 Depth Texture 同类:没人读就关。
建议:如果没有折射或扭曲效果依赖 Opaque Texture,就保持关闭;一旦开启,必须明确具体由哪个效果使用。
反射探针混合和盒投影
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 关 | 开 |
反射探针存的是环境反射。混合让物体在两枚探针之间过渡时不要突然换环境;盒投影让室内反射按房间形状贴,而不是按一个圆球贴。画面上是镜子、地面、金属的环境更稳,采样和计算更贵。
| 性能消耗 | 画面差 |
|---|---|
| 中 | 中等 |
Unity 对低端移动的建议就是关掉这两项。没有反射探针、没有大块金属和室内镜面,开了等于空转。
建议:只有在场景确实使用反射探针,并且探针过渡或室内反射问题明显时,才考虑开启;开启前要确认目标设备仍有足够的性能余量。
SSAO
| Performant | Balanced | High Fidelity |
|---|---|---|
| 无 | 有(降采样) | 有(更高精度) |
SSAO 是屏幕空间环境光遮蔽:用深度(有时加法线)估像素周围挡没挡住光,把缝、洞、交叉、贴在一起的表面压暗。墙角、洞窟、箱子贴地、角色衣服夹缝会多一层脏暗,体积感出来。它是 Renderer Feature,和 Bloom 那种 Volume 后处理不是一回事,通常还要深度图。
| 性能消耗 | 画面差 |
|---|---|
| 高 | 轻微 |
消耗性能的地方在于全屏多 Pass。URP 这份实现里,采样半径、采样数官方标的性能影响是 High,模糊质量和降采样是 Very high(降采样是用分辨率换性能)。知乎上拆过 URP SSAO:算完要走采样再走几次模糊,低端机上就是典型填满。
画面差完全取决于几何。官方说明也是 crease、hole、intersection、靠近的表面。没有洞窟、没有深墙角、没有物体贴地贴墙,开不开几乎没影响------大厅、卡牌桌、偏平的 UI 场景最容易白开。强度拉高还会在角色脸上、平面上脏一圈,观感不一定更好。
建议:如果场景里的墙角、接触面用不上这层暗部细节,或者中低端设备的 fill、深度图成本已经吃紧,可以移除 SSAO。要保留 SSAO,就要把深度图成本一起算进去,并且只给真正有缝隙、孔洞和交叉面的场景开启。
后处理
| Performant | Balanced | High Fidelity |
|---|---|---|
| 挂后处理数据 | 挂后处理数据 | 挂后处理数据 |
后处理是画完场景之后整屏再滤一层:Bloom 把亮部散出发光,Tonemapping 把 HDR 压回能显示的范围,Vignette 压四角,DOF、Motion Blur 再单独算。Renderer 上要挂后处理数据,场景里还要有 Volume 打开对应效果,两边缺一不可。模板场景的 Volume 里有 Bloom、Vignette、Tonemapping。
| 性能消耗 | 画面差 |
|---|---|
| 中~高 | 中等 |
每一项都是全屏 Pass。Bloom 在有 autolight、爆炸、金属高光时一眼能看出;没有过亮像素,开着也只是略雾。DOF、Motion Blur 更贵,电影镜头才用得上,玩法视角一关几乎没人记得住。
建议:如果项目没有使用 Bloom / Tonemapping,或者中低端设备的全屏 Pass 已经吃紧,后处理数据可以不挂载,对应的 Volume 效果也不会执行。DOF、Motion Blur 即便挂了后处理数据,也不建议在移动端默认开启。
SRP Batcher
| Performant | Balanced | High Fidelity |
|---|---|---|
| 开 | 开 | 开 |
SRP Batcher 是 URP 的默认提交路径:同一套 shader 变体下,多次绘制少做一次渲染状态整理,Draw 次数不一定少,但每次更便宜。它不合并网格,也不替代 Instancing。
| 性能消耗 | 画面差 |
|---|---|
| 无,是性能优化项 | 无 |
这是提交路径,不是画质开关。材质不兼容时开了也没用。
建议:保持开启。如果材质不兼容,或者 shader 变体过于分散,即使开关开启,Frame Debugger 里也看不到 SRP Batch;这时应先治理材质和变体,细节放到渲染篇讨论。
动态合批
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 关 | 关 |
动态合批是每帧把合格的小网格在 CPU 上变换、拼成一批再提交,用来减少很小、会动的物体的 Draw。限制很死,拼 mesh 本身也吃 CPU。
| 性能消耗 | 画面差 |
|---|---|
| 视 CPU | 无 |
官方三档都关。Batches 降了但 CPU 更忙,就是负优化。
建议:默认关闭。如果要开启,必须用真机 A/B 验证;只看到 Batches 下降还不够,如果 CPU 侧更忙,就应该关闭。
lodBias
| Performant | Balanced | High Fidelity |
|---|---|---|
| 0.4 | 1 | 2 |
lodBias 在 Quality 面板,不在 URP Asset 里。它乘在 LOD 切换距离上:数字越大,越晚切到低模,近处更精细,同屏面数更高。
| 性能消耗 | 画面差 |
|---|---|
| 中(面数) | 中等 |
没有 LOD 组,改这个没效果。远景物件较多时,数值过大会明显增加顶点处理压力。
建议:如果中低端设备的面数压力已经很高,可以降到 0.4。不要为了远景精细度直接使用 2,除非远景物件很多,并且目标设备仍有足够的顶点处理余量。档位越高,才应该越晚切到低模。
蒙皮权重
| Performant | Balanced | High Fidelity |
|---|---|---|
| 2 | 4 | 255 |
蒙皮权重是蒙皮网格上每个顶点最多跟几根骨骼。2 根够大多数角色;4 根关节更圆;255 基本是「全开」,给 PC 看的。
| 性能消耗 | 画面差 |
|---|---|
| 低~中 | 中等 |
没有蒙皮角色,无差。关节多的手指、衣摆,2 和 4 能看出圆不圆。
建议:如果角色没有复杂关节,或者中低端设备的蒙皮成本已经吃紧,可以降到 2。移动端不要使用 255。
各向异性
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | Per Texture | Full |
各向异性过滤是贴图被斜着看时,减少地面、墙壁那种一拉就糊的感觉。关着最便宜;Per Texture 只对开了各向异性的贴图生效;Full 全开最贵。
| 性能消耗 | 画面差 |
|---|---|
| 低~中 | 中等 |
摄像机几乎平视 UI、没有大块地面,关了看不出。
建议:如果镜头里几乎不会斜看地面和墙壁,或者中低端设备已经吃紧,可以关闭各向异性过滤。移动端不要使用 Full。
垂直同步
| Performant | Balanced | High Fidelity |
|---|---|---|
| 关 | 开 | 开 |
垂直同步让出帧对齐屏幕刷新,能减撕裂,也可能把帧率锁在刷新率上,并在等刷新时把 CPU 堵住。它不管画得好不好,管的是出帧节奏。
| 性能消耗 | 画面差 |
|---|---|
| 中(等刷新) | 无 |
手机更适合用 targetFrameRate。
建议:如果垂直同步导致 CPU 等待刷新,中低端设备上的影响会更明显,可以在 Quality 里关闭。
Quality 里还有 pixelLightCount、shadows、shadowCascades 这些 Built-in 遗留项。URP 下以 Pipeline Asset 为准,改 Quality 的 Shadow Distance,不会改 URP Asset 里的 50。
切档接到工程里
官方是 Quality 每一档指向一份 Pipeline Asset。Graphics 默认管线指向 High Fidelity;Android / iOS 的平台默认档是 Balanced。运行时按设备能力切一次即可:
pseudo
function applyGraphicsTier():
tier = deviceTier.evaluate()
asset = pipelineAssets.forTier(tier) // Performant / Balanced / High Fidelity
qualitySettings.renderPipeline = asset
log("graphics tier applied", tier)
- 切换放在加载阶段之前,进场景后再切会画质跳变,阴影和光照还会在中途重新初始化
- Quality 档位、平台默认档、运行时切档入口必须指向同一套 Asset,一对一。两处引用不一致,档位变了管线没变
- 关了主光阴影,软阴影、附加光阴影一起关,和官方 Performant 一致
设备怎么评级是后面设备分级篇的事,这里只消费结果。
怎么查看
- Unity Profiler(CPU / GPU Frame Time、Main Thread / Render Thread):每个开关改动前后各采一组。连线真机本身有开销,趋势可用,绝对值慎用
- Frame Debugger :确认关掉的阴影、拷贝、后处理、SSAO 对应的 Pass 真的消失了。「参数关了但 Pass 还在」只有这里能直接证实
- 真机 + Release 包:Editor 只能快速迭代,结论以真机 Release 为准。快速回归用 SoloPi 看帧率 / CPU / 温度,长期用 UPR 分机型沉淀
- 每次只改一个开关,记 CPU / GPU / 内存。批量改无法归因
建议怎么落地
不要把这篇当成「每个项目都照抄的参数表」。更稳的做法是把它变成一张项目内的 URP 设置评审表,每个开关只回答四个问题:
- 这个效果在当前项目里有没有真实使用场景?
- 关掉以后,目标场景里的画面差是轻微、中等,还是明显?
- 它主要消耗 CPU 提交、GPU fill、带宽、显存,还是 shader 变体?
- 它应该保留在哪些设备档位,高端、中端、低端是否一致?
落地顺序建议这样走:
- 先以官方 Balanced 作为手机基线,不直接套 High Fidelity,也不要一上来压到 Performant;
- 把低端机最贵的项先收掉:实时阴影、SSAO、后处理、HDR、全屏纹理、MSAA;
- 对画面差明显的项,比如主光阴影,不要只做开关选择,要准备替代方案:烘焙、Blob Shadow、贴片阴影、低距离实时阴影;
- 对画面差轻微的项,比如很多偏平场景里的 SSAO,优先从低端和中端移除,把预算留给更容易被玩家看到的效果;
- 每改一项都用 Frame Debugger 确认 Pass 真的少了,再用真机 Release 看帧时间、温度和内存,不要只看 Editor 画面感觉。
最后,把这些结论固化到三份 Pipeline Asset 和 Quality 档位里,而不是靠口头约定。新增效果时也按同一张表过一遍:先说明收益,再说明成本,最后说明哪些设备档位能开。
容易犯的错误
- 把 High Fidelity 当手机默认:官方把 Android / iOS 的默认档设成 Balanced,Standalone 才是 High Fidelity
- Quality 和 Pipeline Asset 对不上:官方是一档一份。两处引用不一致,切档会没效果
- 关了主光阴影,软阴影还开着:官方 Performant 是一起关的。留下去没有画面,只会干扰变体
Opaque/Depth Texture开了没人用:效果砍了开关还在,低配机白扛全屏拷贝。开启前必须明确具体使用者- SSAO 当必开项:官方 Balanced 就挂了。没有缝、洞、贴合面,开不开几乎看不出,中低端 fill 却先满
- 只改 Quality 里的 Shadow Distance / Cascades:URP 不吃这几个 Built-in 项,要改 URP Asset
总结
- 移动端 URP 设置的核心不是追最高画质,而是把画质成本按设备档位分配清楚。 手机默认从 Balanced 起步,高端机可以保留更多效果,中低端要主动收掉不稳定、收益低或成本高的项。
- 每个开关都要同时看「性能消耗」和「画面差」。 主光阴影关掉会直接少投影,属于明显画面变化;SSAO 只在缝隙、孔洞、交叉面丰富时才容易体现,很多偏平场景里差异很轻。不能只按开关名字判断重要性。
- 低端机优先砍全屏和实时项。 HDR、SSAO、后处理、MSAA、Depth/Opaque Texture、实时阴影都会直接打到带宽、fill 或额外 Pass;项目没用到,或者玩家看不出,就不要让低端机长期背这个成本。
- 画面差明显的项要准备替代方案,而不是粗暴关闭。 阴影可以用烘焙、Blob Shadow、贴片或短距离实时阴影兜底;后处理可以只保留最关键的一项;HDR 可以只给确实依赖 Bloom/Tonemapping 的档位。
- 所有结论都要落到可验证的 Asset 和流程里。 三档 Pipeline Asset、Quality 默认档、运行时切档入口要一一对应;改完用 Frame Debugger 确认 Pass 消失,用真机 Release 看帧时间、温度和内存,Editor 只负责快速迭代。