Quick answer: Set both QualitySettings.renderPipeline and GraphicsSettings.defaultRenderPipeline, then reload the scene if materials don’t rebind.

A graphics-options screen lets the player swap between Low and High URP assets. Setting GraphicsSettings.defaultRenderPipeline = highAsset at runtime does nothing visibly — the previous asset stays active.

Two Levels of Pipeline Assignment

Unity reads the active pipeline from two places:

  1. QualitySettings.renderPipeline — per-quality-level override. Checked first.
  2. GraphicsSettings.defaultRenderPipeline — fallback when Quality has no override.

If the current quality level has a non-null QualitySettings.renderPipeline, setting GraphicsSettings.defaultRenderPipeline doesn’t affect the runtime — the Quality value takes precedence.

The Fix

using UnityEngine.Rendering;

public class PipelineSwitcher : MonoBehaviour
{
    [SerializeField] RenderPipelineAsset lowAsset;
    [SerializeField] RenderPipelineAsset highAsset;

    public void SetHighQuality() {
        QualitySettings.renderPipeline = highAsset;
        GraphicsSettings.defaultRenderPipeline = highAsset;
        StartCoroutine(RefreshShaders());
    }

    IEnumerator RefreshShaders() {
        yield return null;
        Resources.UnloadUnusedAssets();
    }
}

Both fields are updated. UnloadUnusedAssets after a frame nudges Unity to rebind materials against the new pipeline.

Quality-Level Driven Switching

For projects using the standard Quality system:

// Each quality level has its own RP asset configured in Project Settings
QualitySettings.SetQualityLevel(3, applyExpensiveChanges: true);

Switching quality level activates the matching pipeline asset automatically. Cleaner than manual assignment if your project follows the standard Quality ↔ Asset mapping.

When a Scene Reload Helps

Some swaps don’t fully take effect until materials rebind. Reloading the scene forces a clean rebind:

SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

Costly (scene reset, asset reload) but bulletproof.

Diagnosing

Print the current pipeline:

Debug.Log($"Quality: {QualitySettings.renderPipeline?.name}");
Debug.Log($"Default: {GraphicsSettings.defaultRenderPipeline?.name}");
Debug.Log($"Current: {GraphicsSettings.currentRenderPipeline?.name}");

currentRenderPipeline is the active one. If Current matches what you intended but visuals look wrong, materials are caching the old shader variants — reload the scene.

Verifying

Swap quality at runtime. currentRenderPipeline should show the new asset name. Visual changes (different shadow quality, post-processing) should be visible.

“Quality wins over Graphics. Set both, or your runtime swap doesn’t reach the renderer.”

For per-platform settings, configure the Quality Levels in Project Settings rather than scripting — cleaner authoring, less runtime risk.