Overview
A URP project with many physically based (PBR) Shader Graph materials pays for them in three places. The CPU prepares and submits draw calls. The GPU shades every pixel, so cost depends on the shading model, the number of texture samples and overdraw. The build compiles shader variants, which takes build time and memory. Balancing fidelity against performance means keeping each of these under control: keep materials batchable, keep the number of distinct shaders and variants small, give expensive shading only to the objects that need it, and give each platform its own quality settings. Measure first; the tools are at the end of this page.
For general shader-cost theory (why texture samples and branches cost, channel packing, mipmaps), see shader-fundamentals. For what URP is and how its assets fit together, see unity-urp-overview.
Setup
- SRP Batcher on. It is a setting on the URP Asset, visible only with Show All Advanced Properties enabled. Unity’s reference recommends it when you have many materials that use the same shader, and warns that on low-end devices a project whose shaders are not optimised for it may run better with it off (Unity Technologies, Unity Manual: Universal Render Pipeline asset reference for URP).
- One URP Asset per quality tier. In Project Settings > Quality, select each quality level and assign a URP Asset to its Render Pipeline Asset field. “For each quality level in the Quality settings window, Unity uses the render pipeline asset assigned to Render Pipeline Asset”; if the field is empty, Unity falls back to the default asset in Graphics settings, and the manual suggests “different render pipeline assets for different hardware quality levels” (Unity Technologies, Unity Manual: Change or detect the active render pipeline). The platform columns in the Quality settings choose which levels each platform includes and which is its default.
- Stripping on. In Project Settings > Graphics, under URP’s settings, enable Strip Unused Variants, Strip Unused Post Processing Variants and Strip Screen Coord Override Variants (unless you use multi-display cluster rendering) (Unity Technologies, Unity Manual: Reduce shader variants in URP).
Usage
1. Keep materials SRP Batcher compatible
The SRP Batcher “reduces the CPU time Unity requires to render scenes with many materials that use the same shader variant”, and you “can still use as many different materials with the same shader as you want” (Unity Technologies, Unity Manual: Scriptable Render Pipeline Batcher in URP). The practical consequence is that many materials built from a few Shader Graphs are cheap; many different Shader Graphs, or many keyword combinations of one graph, are not. Build a small set of master graphs with exposed properties and make materials from them, rather than a new graph per object.
- Check a shader. Select the shader (or Shader Graph) asset; “you can check the compatibility status of a shader in the Inspector panel” (Unity Technologies, Unity Manual: Check whether a GameObject is compatible with the SRP Batcher in URP). Shader Graph’s URP shaders are normally compatible: Unity’s page on removing compatibility says that making a Shader Graph shader incompatible requires copying its compiled code into a new shader file (Unity Technologies, Unity Manual: Remove SRP Batcher compatibility for GameObjects in URP).
- What breaks it. A GameObject must have a mesh or skinned mesh (“It can’t be a particle”) and “mustn’t use MaterialPropertyBlocks”. URP’s Lit and Unlit shaders meet the shader requirements, except their particle versions (Unity Technologies, Unity Manual: Check whether a GameObject is compatible with the SRP Batcher in URP). Hand-written shaders must put material properties in a
UnityPerMaterialconstant buffer. If you need per-object variation (a tint, a hit flash) on many objects, a separate material instance per object keeps the SRP Batcher working, whereas aMaterialPropertyBlockdoes not (see the hit flash discussion in vfx-shape-and-timing). - Check at runtime. Open Window > Analysis > Frame Debugger. Each SRP Batch shows why it was not merged with the previous one, for example “Nodes have different shaders”, and many SRP batches with few draw calls each “often means the project uses too many shader variants” (Unity Technologies, Unity Manual: Troubleshoot the SRP Batcher in URP).
2. Keep shader variants under control
Every keyword combination a shader can use is a separate compiled variant. Variants slow builds, take memory and break SRP batches.
- Shader Graph keywords. Each Boolean or Enum keyword multiplies the number of variants. Prefer an ordinary property (a Float multiplied in, or a texture set to black) when a feature differs only by a value. When you do need a keyword, set its Definition to Shader Feature rather than Multi Compile, so variants no material uses can be left out of the build.
- Turn off URP features you do not use. “If you disable features in the URP Asset, URP automatically excludes (‘strips’) the related shader variants”, for example additional-light shadows or additional lights. A feature is only stripped if it is disabled in every URP Asset in the build (Unity Technologies, Unity Manual: Reduce shader variants in URP).
- Keep one rendering path. “Avoid including URP Assets in your build that use different rendering paths because this causes Unity to create two sets of variants for each keyword” (same source). Quality tiers should differ in settings such as shadows and MSAA, not in Forward versus Forward+ versus Deferred, unless you accept the extra variants.
- Count them. In Graphics settings under Shader Stripping, choose a logging level other than Disabled, build, and search
Editor.logfor “ShaderStrippingReport”; Export Shader Variants writes the full list to the project’sTempfolder (same source).
3. Give expensive shading only to what needs it
URP’s prebuilt shaders differ a lot in cost (Unity Technologies, Unity Manual: Choose a prebuilt shader in URP):
| Shader | Cost and use, per the manual |
|---|---|
| Complex Lit | Some features “might be considerably more resource-intensive”; needs Shader Model 4.5 hardware |
| Lit | PBR; “uses the most computationally heavy shading model” in URP |
| Simple Lit | Non-PBR; “use this Shader when performance is more important than photorealism”; renders quickly. Shader Graph does not support it |
| Baked Lit | For baked lighting only; no real-time lighting, so it is faster to calculate |
| Unlit | No lighting calculations; “optimal for lower-end hardware” |
In practice, keep the Lit target (or a full PBR Shader Graph) for hero assets and objects close to the camera. Use Simple Lit or Baked Lit materials for background props and static scenery, and Unlit for anything whose look does not depend on lights (skyboxes, UI-like elements, many stylised effects). Because Shader Graph has no Simple Lit target, a cheap Shader Graph version usually means an Unlit graph, possibly with baked or faked lighting.
- Material LOD. A LOD Group can swap more than the mesh: give the lower LOD renderers a cheaper material (Simple Lit or Unlit, fewer texture samples, no detail maps). Distant objects are small on screen, so the loss of fidelity is rarely visible.
- Fewer texture samples. Pack greyscale masks (metallic, occlusion, smoothness) into the channels of one texture, and remove maps that do not visibly change the result; see “Why branches and texture samples cost” in shader-fundamentals.
- Emission and transparency. The Lit material’s Emission property “affects batching performance” (Unity Technologies, Unity Manual: Lit shader material Inspector window reference for URP), and transparent materials cause overdraw, so use both where they earn their cost.
4. Scale settings per platform
The URP Asset assigned to each quality level controls most of the frame cost. On lower tiers, Unity’s performance guidance suggests: disable HDR if you do not need it (or keep HDR Precision at 32 bit), disable the Depth and Opaque Textures unless something uses them, reduce or disable MSAA, set Additional Lights to Disabled or Per Vertex (Forward path), reduce shadow resolution, shadow distance and cascade count, and disable soft shadows or lower their quality (Unity Technologies, Unity Manual: Configure for better performance in URP). To let players choose, switch levels at runtime:
QualitySettings.SetQualityLevel(lowTierIndex, applyExpensiveChanges: true);5. Many copies of the same mesh: GPU Resident Drawer
Unity 6 adds the GPU Resident Drawer, which uses the BatchRendererGroup API to draw GameObjects with GPU instancing; it suits large scenes where “multiple GameObjects use the same mesh”. It needs the Forward+ rendering path, the SRP Batcher, BatchRendererGroup Variants set to Keep All in Graphics settings, and a graphics API with compute shaders (not OpenGL ES), and it lengthens build times (Unity Technologies, Unity Manual: Enable the GPU Resident Drawer in URP). Treat it as an option to profile, not a default.
6. Measure before and after
- Profiler. Find out whether the frame is CPU-bound or GPU-bound before optimising materials, and profile on the target device rather than in the Editor; see unity-profiler.
- Frame Debugger (Window > Analysis > Frame Debugger). Step through the frame, see each SRP Batch and why batches split.
- Rendering Debugger (Window > Analysis > Rendering Debugger; LeftCtrl+Backspace in Play mode or a development build). It “lets you visualize various lighting, rendering, and Material properties” (Unity Technologies, Unity Manual: Rendering Debugger in URP). Useful views for material cost are Rendering > Overdraw, which shows where pixels are drawn over one another, and Material > Material Override > LightingComplexity, which shows how many lights affect each area. Material Validation highlights albedo or metallic values outside a range you set, which helps catch implausible PBR values (Unity Technologies, Unity Manual: Rendering Debugger window reference for URP). In a build, only the Display Stats panel is available unless you disable Strip Debug Variants (Unity Technologies, Unity Manual: Enable the Rendering Debugger in URP).
A workflow for a scene with many PBR materials (practice, not a Unity checklist): profile on the weakest target device; in the Frame Debugger, check that most draws sit in SRP batches and look at the reasons batches split; merge near-duplicate Shader Graphs into a few master graphs; remove unneeded keywords; move background objects to cheaper shaders and add cheaper LOD materials; check overdraw and lighting complexity in the Rendering Debugger; then set up lower quality tiers. Re-profile after each change, so you know which one helped.
Gotchas
- A
MaterialPropertyBlockon a renderer removes it from the SRP Batcher, even if the shader is compatible. - Particles are never SRP-batched, so a particle-heavy scene is costed differently; check overdraw first.
- Each Shader Graph Boolean keyword can double that shader’s variants. A few keywords on a widely used master graph can add up to thousands of variants.
- Disabling a URP feature in only some of the URP Assets in a build prevents URP from stripping its variants.
- Mixing rendering paths (Forward, Forward+, Deferred) across quality-level URP Assets doubles the variants.
- Shader Graph has no Simple Lit target; for a cheap Shader Graph material, use an Unlit graph.
- Editor frame rates are not device frame rates. Always confirm improvements on the target hardware.
Related
unity-urp-overview · shader-graph-overview · shader-fundamentals · unity-lod-groups · unity-profiler · unity-urp-lighting-and-render-features · vfx-value-and-colour · vfx-shape-and-timing · source-unity-performance-mobile-xr-web