HDRP/LWRP detection from Editor script

Is there a correct way of detecting which scriptable render pipeline is being used from an Editor script? HDRP/LWRP/Built-in (legacy)

1 Like

In a script, how can I check if HDRP is being used?

You can check what pipeline unity is currently using:

using UnityEngine.Rendering;

if (GraphicsSettings.renderPipelineAsset is HDRenderPipelineAsset)
{
    // Do action if the project is using the HDRP pipeline...
}
else if (GraphicsSettings.renderPipelineAsset is LightweightPipelineAsset)
{
    // Do action if the project is using the LWRP pipeline...
} 
else
{
 // Do action if we use the legacy pipeline
}
2 Likes

Ok. That assume you have “using UnityEngine.Experimental.Rendering.HDPipeline.HDRenderPipelineAsset” AND LightWeight already in your project. Maybe we need to check if the types exist. I was just wondering if there was a more supportable way of doing it.

Maybe something like:

System.Type hdRenderPipeLineAssetType = System.Type.GetType("Unity.RenderPipelines.HighDefinition.Runtime, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null", true, true);
if (hdRenderPipeLineAssetType != null) { isInstalled = true; }

If you are building for multiple Editor versions, you could check the GraphicsSetting’s RenderPipelineAsset type:

string assetTypeHDRP = "HDRenderPipelineAsset";
bool IsHDRP()
{
            return GraphicsSettings.renderPipelineAsset.GetType().Name.Contains(assetTypeHDRP);
}

No better way to do this yet?

Something like this should work :

   static ListRequest request;
foreach (UnityEditor.PackageManager.PackageInfo package in request.Result)
 {
               if (package.name.Contains("render-pipelines.universal"))
                {

                }
             else if (package.name.Contains("render-pipelines.high-definition"))
                {

                }
}

The best way i found so far is this:

using UnityEngine.Rendering;

if(GraphicsSettings.renderPipelineAsset == null){

   //do action

} else {
            
   //do action
            
}

It seems I came across the same problem as you guys so I made a half-decent solution: A solution to detecting Unity's active RenderPipeline ($2026367) ¡ Snippets ¡ GitLab

It uses the [UnityEditor.Callbacks.DidReloadScripts] attribute to get an editor callback on script recompilation to then check if the RenderPipeline packages are installed in the package manager. It then adds or removes from the PlayerSettings define symbols ‘USING_HDRP’ and ‘USING_URP’. It also creates a separate c# file that has bool constants named the same.

Just stick it in a separate folder like RCFolder/Editor/RCRenderPipeline.cs as the generated file will be made in the RCFolder so it is kept with standalone builds.

Example use:

// Outside code


#if USING_HDRP
// only HDRP code
#endif

#if USING_URP
// only URP code
#endif

#if !USING_HDRP && !USING_URP
// only Default renderer code
#endif

// Outside code
using System;
using System.IO;
using System.Linq;
using System.Collections;
using System.Threading.Tasks;
using System.Collections.Generic;

using UnityEngine;
using UnityEditor;

using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;




namespace RealCode
{
    public static class RCRenderPipeline
    {

        private const bool LOG_NEW_DEFINE_SYMBOLS = true;

        private const string HDRP_PACKAGE = "render-pipelines.high-definition";
        private const string URP_PACKAGE = "render-pipelines.universal";

        private const string TAG_HDRP = "USING_HDRP";
        private const string TAG_URP = "USING_URP";

        private const string CS_CLASSNAME = "RCDefinedRenderPipeline";
        private const string CS_FILENAME = CS_CLASSNAME + ".cs";





        [UnityEditor.Callbacks.DidReloadScripts]
        private static void OnScriptsReloaded()
        {

            ListRequest packagesRequest = Client.List(true);

            LoadPackages(packagesRequest);

        }
        private static void LoadPackages (ListRequest request)
        {

            if (request == null)
                return;


            // Wait for request to complete
            for (int i = 0; i < 1000; i++)
            {
                if (request.Result != null)
                    break;
                Task.Delay(1).Wait();
            }
            if (request.Result == null)
                throw new TimeoutException();

            // Find out what packages are installed
            var packagesList = request.Result.ToList();

            ///Debug.Log("List of offline Unity packages:\n\n" + String.Join("\n", packagesList.Select(x => x.name)) + "\n\n");

            bool hasHDRP = packagesList.Find(x => x.name.Contains(HDRP_PACKAGE)) != null;
            bool hasURP = packagesList.Find(x => x.name.Contains(URP_PACKAGE)) != null;

            if(hasHDRP && hasURP)
                Debug.LogError("<b>RenderPipeline Packages:</b> Both the HDRP and URP seem to be installed, this may cause problems!");


            DefinePreProcessors(hasHDRP, hasURP);
            SaveToFile(CSharpFileCode(hasHDRP, hasURP));

        }



        private static void DefinePreProcessors(bool defineHDRP, bool defineURP)
        {

            string originalDefineSymbols;
            string newDefineSymbols;

            List<string> defined;
            //List<BuildTargetGroup> avaliablePlatforms = Enum.GetValues(typeof(BuildTargetGroup)).Cast<BuildTargetGroup>().ToList();
            BuildTargetGroup platform = EditorUserBuildSettings.selectedBuildTargetGroup;

            string log = string.Empty;

            // foreach(var platform in avaliablePlatforms)
            originalDefineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(platform);
            defined = originalDefineSymbols.Split(';').Where(x => !String.IsNullOrWhiteSpace(x)).ToList();


            Action<bool, string> AppendRemoveTag = (stat, tag) =>
            {
                if (stat && !defined.Contains(tag))
                    defined.Add(tag);
                else if (!stat && defined.Contains(tag))
                    defined.Remove(tag);
            };

            AppendRemoveTag(defineHDRP, TAG_HDRP);
            AppendRemoveTag(defineURP, TAG_URP);

            newDefineSymbols = string.Join(";", defined);
            if(originalDefineSymbols != newDefineSymbols)
            {
                PlayerSettings.SetScriptingDefineSymbolsForGroup(platform, newDefineSymbols);
                log += $"<color=yellow>{platform.ToString()}</color> Old Define Symbols:\n - <color=red>{originalDefineSymbols}</color>\n";
                log += $"<color=yellow>{platform.ToString()}</color> New Define Symbols:\n - <color=green>{newDefineSymbols}</color>\n";
            }
            // }

            if (LOG_NEW_DEFINE_SYMBOLS && !String.IsNullOrEmpty(log))
                Debug.Log($"<b>{nameof(RCRenderPipeline)}:</b> PlayerSetting Define Symbols have been updated! Check log for further details.\n{log}");

        }

        private static void SaveToFile (string Code)
        {

            // Get working directory to save the file to
            var directory = Directory.GetParent(new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName());
            if(directory != null && directory.Parent != null)
                directory = directory.Parent;

            ///Debug.Log(directory.FullName);
            File.WriteAllText(directory.FullName + "\\" + CS_FILENAME, Code);

        }
        private static string CSharpFileCode (bool defineHDRP, bool defineURP)
        {

            Func<bool, string> ToString = (b) => b ? "true" : "false";

            return "namespace RealCode\n" +
            "{\n" +
                $"\tpublic static class {CS_CLASSNAME}\n" +
                "\t{\n\n" +

                    $"\t\tpublic const bool USING_HDRP = {ToString(defineHDRP)};\n\n" +

                    $"\t\tpublic const bool USING_URP = {ToString(defineURP)};\n\n" +

                "\t}\n" +
            "}";

        }


    }
}
3 Likes

If filtering by active RP asset is enough, you could do this and it wouldn’t require both HDRP and URP on same package:

if (GraphicsSettings.currentRenderPipeline)
{
   if (GraphicsSettings.currentRenderPipeline.GetType().ToString().Contains("HighDefinition"))
   {
      Debug.Log("HDRP active");
   }
   else // assuming here we only have HDRP or URP options here
   {
      Debug.Log("URP active");
   }
}
else
{
   Debug.Log("Built-in RP active");
}

Worth noting that ToString() there does generate garbage so don’t try to do this every update, it’s fine on start / one shots though.

As for package detection, there’s a built-in mechanism on Unity for this already. Basically you can force Unity make custom defines via assembly definition file if there’s some specific package installed.

Here’s what I’ve used to check if there’s SRP core package >= v5.0 installed:

(you can just substitute that with whatever package you want)

More info about asmdef’s here: Unity - Manual: Assembly definitions

3 Likes

Very old thread, but if anyone else is wondering: If you’re using Assembly Definitions (.asmdef), you can modify your own code’s .asmdef JSON to include this:

{
"name": "com.unity.render-pipelines.universal",
"expression": "0.0",
"define": "USING_URP"
},
{
"name": "com.unity.render-pipelines.high-definition",
"expression": "0.0",
"define": "USING_HDRP"
}
],```

Which will allow you to write something like this:

```csharp
        static string GetUnlitShader()
        {
#if USING_URP
            return "Universal Render Pipeline/Unlit";
#elif USING_HDRP
            return "HDRP/Unlit";
#else
            return "Unlit/Color";
#endif
        }

Unfortunately, you’ll need to add this define to every Assembly Definition file that you’d like to query this.

Also note: GraphicsSettings.currentRenderPipeline has some defaultMaterials (defaultUnlitMaterial may be added at some point).

11 Likes

Exactly what I was hoping to find. Thank you.

Setting defines from c# script in Assets/Editor folder, by @MUGIK :

work for me. But in Visual Studio, the code that is wrapped in #if USING_URP #endif is greyed out, but in the Player, the code runs as if it wasn’t greyed out.
Is that normal?

Unfortunately yes. I’ll ask around about whether or not this is being improved.

Hi, Niki. But… I’m doing an asset for the asset store. I can’t mess with buyer’s .asmdef json files.

I’m trying to do something like this, in an asset for every render pipeline.

            //destroy some components to obtain a simplified version of the object
#if USING_URP
            foreach (UniversalAdditionalCameraData cam in clone.GetComponentsInChildren<UniversalAdditionalCameraData>()) Destroy(cam);
#endif
            foreach (Camera cam in clone.GetComponentsInChildren<Camera>()) Destroy(cam);

Unity should have some solution for this. If I don’t remove the UniversalAdditionalCameraData component first, I can’t remove the Camera component. But If that line remains in BIRP, wlll cause error because it doesn’t know the UniversalAdditionalCameraData class.

Perhaps this might be of use in your situation?

I can’t say for sure, but it might. Worth a try, at least.

That’s fine: You would modify your assets .asmdef, not the buyers .asmdefs.

The way it works is: If your .asmdef detects the presence of the HDRP package (in the buyers project), your .asmdef will add USING_HDRP to your .asmdef assembly (and recompile it). Likewise for URP. This allows you to add optional, opt-in dependencies, making your product compatible with multiple packages.

1 Like

There isn’t a built-in method in Unity’s scripting API to directly detect which Scriptable Render Pipeline (SRP) is being used from an Editor script. However, you can infer the current SRP being used by checking the active GraphicsSettings.

Here’s a way to infer which SRP is being used:

using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;

public class SRPDetector : EditorWindow
{
    [MenuItem("Tools/Detect SRP")]
    static void DetectSRP()
    {
        // Check if the active rendering path is set to Scriptable Render Pipeline
        if (GraphicsSettings.renderPipelineAsset != null)
        {
            Debug.Log("Using a Scriptable Render Pipeline (HDRP/LWRP/URP)");
            if (GraphicsSettings.renderPipelineAsset is HDRenderPipelineAsset)
            {
                Debug.Log("High Definition Render Pipeline (HDRP) is being used.");
            }
            else if (GraphicsSettings.renderPipelineAsset is UniversalRenderPipelineAsset)
            {
                Debug.Log("Universal Render Pipeline (URP) is being used.");
            }
            // Add more checks for other SRPs as needed
        }
        else
        {
            Debug.Log("Using Built-in (Legacy) Render Pipeline");
        }
    }
}

In this script:

  • We use the GraphicsSettings.renderPipelineAsset property to check if an SRP is assigned. If it’s assigned, it indicates that you are using an SRP (either HDRP, LWRP/URP, or another custom SRP).

  • We then check the type of the assigned asset to determine which SRP it is. You can add more checks for other SRPs if needed.

  • If no SRP is assigned, it means you are using the Built-in (Legacy) Render Pipeline.

1 Like