Built-in Render Pipeline to URP in Unity 6: The Migration Checklist

Unity 6.5 deprecated the Built-in Render Pipeline. When to move to URP, what the converter misses, and how to port custom shaders and post-processing.

This checklist follows the order the work actually happens in: decide, back up, convert what Unity can convert for you, then fix the three things it cannot, which are custom shaders, post-processing, and scripts that hook into rendering. Each step names the exact window or menu, and links to the Unity 6 upgrade pages where an API changed.

Should you migrate now?

When to move to URP

Your situationRecommendationNote
Starting a new projectStart on URPUnity calls Built-in not recommended for new titles, and URP is the default template in Unity 6.
Shipped game, live updates on Built-inPlan it, no rushBuilt-in is supported through the 6.7 LTS lifecycle. Migrate alongside a larger content update rather than in a patch.
Selling assets or teachingMove to URPUnity is asking Asset Store and education content to be URP-compatible by default.
Many custom shaders or OnRenderImage effectsBudget the timeThe converter skips these. Count them first: they are most of the work.

1. Back up first

Unity's documentation is direct about this: the Render Pipeline Converter makes irreversible changes to the project. Commit everything to version control, or copy the project folder, before you open it. Do the migration on a branch so you can compare the old and new look side by side.

Before converting, make a list of every custom shader (search the Project window with t:Shader and ignore Unity's own) and every script that implements OnRenderImage, OnPreRender or OnPostRender. That list is your real estimate.

2. Install URP

  1. Open Window > Package Manager and install Universal RP (com.unity.render-pipelines.universal) for your Unity version.
  2. Do not create the pipeline asset by hand yet: the converter's Rendering Settings step creates the URP asset and Universal Renderer, and converts your Built-in quality settings into them.

3. Run the Render Pipeline Converter

  1. Open Window > Rendering > Render Pipeline Converter.
  2. Choose Built-In Render Pipeline to URP. For a 2D project, choose Built-In Render Pipeline 2D to URP 2D instead.
  3. Tick Rendering Settings (creates the URP asset and renderer from your quality settings), Material Upgrade (converts materials that use Unity's built-in shaders) and Read-only Material Converter (converts built-in read-only materials such as Default-Diffuse).
  4. Initialize the converters, review the list of assets each one will change, then convert.
  5. Check that the new URP asset is assigned in Project Settings > Graphics and on every level in Project Settings > Quality.

What the Material Upgrade converts

Built-in shaderURP shaderNote
Standard, Standard (Specular setup)Universal Render Pipeline/LitURP's physically based shader, metallic or specular workflow.
Standard TerrainUniversal Render Pipeline/Terrain/Lit
Particles/Standard SurfaceUniversal Render Pipeline/Particles/Lit
Particles/Standard UnlitUniversal Render Pipeline/Particles/Unlit
Mobile/* and Legacy Shaders/* (Diffuse, Specular, Bumped, Self-Illumin, Transparent, Cutout)Universal Render Pipeline/Simple LitA cheaper non-PBR shader, close to the legacy look.

4. Convert custom shaders

The Render Pipeline Converter does not touch custom shaders. You have two routes. For most surface-style shaders, rebuilding them in Shader Graph is fastest and keeps them working through future URP changes. For hand-written vertex and fragment shaders, port the code. Built-in surface shaders (#pragma surface) do not work in URP at all, so those need one route or the other.

Porting a vertex and fragment shader comes down to the same handful of changes every time:

  • Add "RenderPipeline" = "UniversalPipeline" to the SubShader tags.
  • Replace CGPROGRAM and ENDCG with HLSLPROGRAM and ENDHLSL.
  • Replace #include "UnityCG.cginc" with #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl".
  • Replace UnityObjectToClipPos(v.vertex) with TransformObjectToHClip(v.positionOS.xyz).
  • Declare textures with TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); and sample with SAMPLE_TEXTURE2D instead of sampler2D and tex2D.
  • Put material properties inside CBUFFER_START(UnityPerMaterial) and CBUFFER_END so the shader works with the SRP Batcher.
  • Lit passes use the "LightMode" = "UniversalForward" tag; Built-in's ForwardBase and ForwardAdd passes have no URP equivalent.
c
Shader "Custom/UnlitTexture"
{
    Properties
    {
        _BaseMap ("Texture", 2D) = "white" {}
        _BaseColor ("Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; };
            struct Varyings   { float4 positionHCS : SV_POSITION; float2 uv : TEXCOORD0; };

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);

            CBUFFER_START(UnityPerMaterial)
                float4 _BaseMap_ST;
                half4 _BaseColor;
            CBUFFER_END

            Varyings vert(Attributes input)
            {
                Varyings output;
                output.positionHCS = TransformObjectToHClip(input.positionOS.xyz);
                output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
                return output;
            }

            half4 frag(Varyings input) : SV_Target
            {
                return SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv) * _BaseColor;
            }
            ENDHLSL
        }
    }
}

GrabPass is not supported in URP. To read what is already on screen, enable Opaque Texture on the URP asset and sample _CameraOpaqueTexture, or use the Scene Color node in Shader Graph.

5. Replace post-processing

URP is not compatible with the Post Processing Stack v2 package. Its post-processing is built in and driven by the Volume framework instead.

  1. Note the effects and values in each Post-process Volume profile.
  2. Add a Global Volume (GameObject > Volume > Global Volume), create a Volume Profile, and add the equivalent overrides, such as Bloom, Tonemapping, Color Adjustments and Vignette.
  3. Enable Post Processing on each camera that should show it.
  4. Remove the Post Processing Stack v2 package once nothing references it.

6. Fix scripts that hook into rendering

This is the part that compiles fine and silently stops working. URP does not call OnRenderImage, OnPreRender or OnPostRender on cameras, and command buffers added with Camera.AddCommandBuffer do not run.

Built-in hook and its URP replacement

Built-inURPNote
OnRenderImage with Graphics.BlitFull Screen Pass Renderer FeatureAssign a full-screen material to the renderer feature; no script needed for simple effects.
OnPreRender / OnPostRenderRenderPipelineManager.beginCameraRendering / endCameraRenderingSubscribe to the static events; they pass the camera being rendered.
Camera.AddCommandBufferA Scriptable Renderer Feature and render passIn Unity 6 the pass implements RecordRenderGraph. See why Execute stops running.
Projector componentURP Decal ProjectorAdd the Decal renderer feature to the Universal Renderer first.
Several cameras sorted by depthCamera StackingOne Base camera with Overlay cameras in its stack.
C#
using UnityEngine;
using UnityEngine.Rendering;

public class CameraHook : MonoBehaviour
{
    void OnEnable()  => RenderPipelineManager.beginCameraRendering += OnBeginCamera;
    void OnDisable() => RenderPipelineManager.beginCameraRendering -= OnBeginCamera;

    void OnBeginCamera(ScriptableRenderContext context, Camera camera)
    {
        // Runs where OnPreRender used to, for every camera URP renders
    }
}

7. Check lighting and look

  • URP's Forward path limits how many lights affect each object. If lights pop or disappear on busy scenes, switch the Universal Renderer to the Forward+ rendering path.
  • Rebake lightmaps and reflection probes, then compare screenshots from the Built-in branch: ambient, fog and shadow defaults differ.
  • Check each Quality level in Project Settings > Quality uses the URP asset you expect, and tune its shadow distance and cascades.
  • Search the project for remaining magenta materials before calling it done.

The checklist

  1. Project committed and on a branch.
  2. Custom shaders and rendering scripts listed.
  3. Universal RP installed; converter run with Rendering Settings, Material Upgrade and Read-only Material Converter.
  4. URP asset assigned in Graphics and every Quality level.
  5. No magenta materials; custom shaders rebuilt in Shader Graph or ported to HLSL.
  6. Post Processing Stack v2 replaced with Volumes, then removed.
  7. OnRenderImage, OnPreRender, OnPostRender and AddCommandBuffer replaced.
  8. Lighting rebaked and compared against the Built-in build.
  9. Scripts checked for other Unity 6 changes with the Unity 6 script checker.

Sources

Written by Mete, the Unity developer who makes Scripts For Unity and shares it free with the community. Articles cite the Unity documentation they rely on, state the Unity version they were written for, and show an updated date only when the text or code changed. How articles are written and checked