Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

HDRP/LWRP detection from Editor script

Discussion in 'Graphics Experimental Previews' started by sstrong, Jul 15, 2018.

  1. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,255
    Is there a correct way of detecting which scriptable render pipeline is being used from an Editor script? HDRP/LWRP/Built-in (legacy)
     
    zwcloud likes this.
  2. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,255
    In a script, how can I check if HDRP is being used?
     
  3. Guerro323

    Guerro323

    Joined:
    Sep 2, 2014
    Posts:
    25
    You can check what pipeline unity is currently using:
    Code (CSharp):
    1. using UnityEngine.Rendering;
    2.  
    3. if (GraphicsSettings.renderPipelineAsset is HDRenderPipelineAsset)
    4. {
    5.     // Do action if the project is using the HDRP pipeline...
    6. }
    7. else if (GraphicsSettings.renderPipelineAsset is LightweightPipelineAsset)
    8. {
    9.     // Do action if the project is using the LWRP pipeline...
    10. }
    11. else
    12. {
    13.  // Do action if we use the legacy pipeline
    14. }
     
    PrimalCoder and EirikWahl like this.
  4. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,255
    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.
     
  5. sstrong

    sstrong

    Joined:
    Oct 16, 2013
    Posts:
    2,255
    Maybe something like:

    Code (CSharp):
    1. System.Type hdRenderPipeLineAssetType = System.Type.GetType("Unity.RenderPipelines.HighDefinition.Runtime, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null", true, true);
    2. if (hdRenderPipeLineAssetType != null) { isInstalled = true; }
    3.  
     
  6. HeyJoeLang

    HeyJoeLang

    Joined:
    Jun 14, 2013
    Posts:
    4
    If you are building for multiple Editor versions, you could check the GraphicsSetting's RenderPipelineAsset type:

    Code (CSharp):
    1.  
    2. string assetTypeHDRP = "HDRenderPipelineAsset";
    3. bool IsHDRP()
    4. {
    5.             return GraphicsSettings.renderPipelineAsset.GetType().Name.Contains(assetTypeHDRP);
    6. }
    7.  
     
  7. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    417
    No better way to do this yet?
     
  8. Benjamin_V

    Benjamin_V

    Joined:
    Apr 1, 2019
    Posts:
    11
    Something like this should work :

    Code (CSharp):
    1.    static ListRequest request;
    2. foreach (UnityEditor.PackageManager.PackageInfo package in request.Result)
    3.  {
    4.                if (package.name.Contains("render-pipelines.universal"))
    5.                 {
    6.  
    7.                 }
    8.              else if (package.name.Contains("render-pipelines.high-definition"))
    9.                 {
    10.  
    11.                 }
    12. }
     
  9. dizzymediainc

    dizzymediainc

    Joined:
    Apr 6, 2014
    Posts:
    433
    The best way i found so far is this:


    Code (CSharp):
    1.              
    2.  
    3. using UnityEngine.Rendering;
    4.  
    5. if(GraphicsSettings.renderPipelineAsset == null){
    6.  
    7.    //do action
    8.  
    9. } else {
    10.            
    11.    //do action
    12.            
    13. }
     
  10. Psycho8Vegemite

    Psycho8Vegemite

    Joined:
    Mar 9, 2013
    Posts:
    8
    It seems I came across the same problem as you guys so I made a half-decent solution: https://gitlab.com/-/snippets/2026367


    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:
    Code (CSharp):
    1. // Outside code
    2.  
    3.  
    4. #if USING_HDRP
    5. // only HDRP code
    6. #endif
    7.  
    8. #if USING_URP
    9. // only URP code
    10. #endif
    11.  
    12. #if !USING_HDRP && !USING_URP
    13. // only Default renderer code
    14. #endif
    15.  
    16. // Outside code
    Code (CSharp):
    1. using System;
    2. using System.IO;
    3. using System.Linq;
    4. using System.Collections;
    5. using System.Threading.Tasks;
    6. using System.Collections.Generic;
    7.  
    8. using UnityEngine;
    9. using UnityEditor;
    10.  
    11. using UnityEditor.PackageManager;
    12. using UnityEditor.PackageManager.Requests;
    13.  
    14.  
    15.  
    16.  
    17. namespace RealCode
    18. {
    19.     public static class RCRenderPipeline
    20.     {
    21.  
    22.         private const bool LOG_NEW_DEFINE_SYMBOLS = true;
    23.  
    24.         private const string HDRP_PACKAGE = "render-pipelines.high-definition";
    25.         private const string URP_PACKAGE = "render-pipelines.universal";
    26.  
    27.         private const string TAG_HDRP = "USING_HDRP";
    28.         private const string TAG_URP = "USING_URP";
    29.  
    30.         private const string CS_CLASSNAME = "RCDefinedRenderPipeline";
    31.         private const string CS_FILENAME = CS_CLASSNAME + ".cs";
    32.  
    33.  
    34.  
    35.  
    36.  
    37.         [UnityEditor.Callbacks.DidReloadScripts]
    38.         private static void OnScriptsReloaded()
    39.         {
    40.  
    41.             ListRequest packagesRequest = Client.List(true);
    42.  
    43.             LoadPackages(packagesRequest);
    44.  
    45.         }
    46.         private static void LoadPackages (ListRequest request)
    47.         {
    48.  
    49.             if (request == null)
    50.                 return;
    51.  
    52.  
    53.             // Wait for request to complete
    54.             for (int i = 0; i < 1000; i++)
    55.             {
    56.                 if (request.Result != null)
    57.                     break;
    58.                 Task.Delay(1).Wait();
    59.             }
    60.             if (request.Result == null)
    61.                 throw new TimeoutException();
    62.  
    63.             // Find out what packages are installed
    64.             var packagesList = request.Result.ToList();
    65.  
    66.             ///Debug.Log("List of offline Unity packages:\n\n" + String.Join("\n", packagesList.Select(x => x.name)) + "\n\n");
    67.  
    68.             bool hasHDRP = packagesList.Find(x => x.name.Contains(HDRP_PACKAGE)) != null;
    69.             bool hasURP = packagesList.Find(x => x.name.Contains(URP_PACKAGE)) != null;
    70.  
    71.             if(hasHDRP && hasURP)
    72.                 Debug.LogError("<b>RenderPipeline Packages:</b> Both the HDRP and URP seem to be installed, this may cause problems!");
    73.  
    74.  
    75.             DefinePreProcessors(hasHDRP, hasURP);
    76.             SaveToFile(CSharpFileCode(hasHDRP, hasURP));
    77.  
    78.         }
    79.  
    80.  
    81.  
    82.         private static void DefinePreProcessors(bool defineHDRP, bool defineURP)
    83.         {
    84.  
    85.             string originalDefineSymbols;
    86.             string newDefineSymbols;
    87.  
    88.             List<string> defined;
    89.             //List<BuildTargetGroup> avaliablePlatforms = Enum.GetValues(typeof(BuildTargetGroup)).Cast<BuildTargetGroup>().ToList();
    90.             BuildTargetGroup platform = EditorUserBuildSettings.selectedBuildTargetGroup;
    91.  
    92.             string log = string.Empty;
    93.  
    94.             // foreach(var platform in avaliablePlatforms)
    95.             originalDefineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(platform);
    96.             defined = originalDefineSymbols.Split(';').Where(x => !String.IsNullOrWhiteSpace(x)).ToList();
    97.  
    98.  
    99.             Action<bool, string> AppendRemoveTag = (stat, tag) =>
    100.             {
    101.                 if (stat && !defined.Contains(tag))
    102.                     defined.Add(tag);
    103.                 else if (!stat && defined.Contains(tag))
    104.                     defined.Remove(tag);
    105.             };
    106.  
    107.             AppendRemoveTag(defineHDRP, TAG_HDRP);
    108.             AppendRemoveTag(defineURP, TAG_URP);
    109.  
    110.             newDefineSymbols = string.Join(";", defined);
    111.             if(originalDefineSymbols != newDefineSymbols)
    112.             {
    113.                 PlayerSettings.SetScriptingDefineSymbolsForGroup(platform, newDefineSymbols);
    114.                 log += $"<color=yellow>{platform.ToString()}</color> Old Define Symbols:\n - <color=red>{originalDefineSymbols}</color>\n";
    115.                 log += $"<color=yellow>{platform.ToString()}</color> New Define Symbols:\n - <color=green>{newDefineSymbols}</color>\n";
    116.             }
    117.             // }
    118.  
    119.             if (LOG_NEW_DEFINE_SYMBOLS && !String.IsNullOrEmpty(log))
    120.                 Debug.Log($"<b>{nameof(RCRenderPipeline)}:</b> PlayerSetting Define Symbols have been updated! Check log for further details.\n{log}");
    121.  
    122.         }
    123.  
    124.         private static void SaveToFile (string Code)
    125.         {
    126.  
    127.             // Get working directory to save the file to
    128.             var directory = Directory.GetParent(new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName());
    129.             if(directory != null && directory.Parent != null)
    130.                 directory = directory.Parent;
    131.  
    132.             ///Debug.Log(directory.FullName);
    133.             File.WriteAllText(directory.FullName + "\\" + CS_FILENAME, Code);
    134.  
    135.         }
    136.         private static string CSharpFileCode (bool defineHDRP, bool defineURP)
    137.         {
    138.  
    139.             Func<bool, string> ToString = (b) => b ? "true" : "false";
    140.  
    141.             return "namespace RealCode\n" +
    142.             "{\n" +
    143.                 $"\tpublic static class {CS_CLASSNAME}\n" +
    144.                 "\t{\n\n" +
    145.  
    146.                     $"\t\tpublic const bool USING_HDRP = {ToString(defineHDRP)};\n\n" +
    147.  
    148.                     $"\t\tpublic const bool USING_URP = {ToString(defineURP)};\n\n" +
    149.  
    150.                 "\t}\n" +
    151.             "}";
    152.  
    153.         }
    154.  
    155.  
    156.     }
    157. }
    158.  
     
    Last edited: Oct 9, 2020
    NotaNaN, Meatloaf4 and _slash_ like this.
  11. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    If filtering by active RP asset is enough, you could do this and it wouldn't require both HDRP and URP on same package:

    Code (CSharp):
    1. if (GraphicsSettings.currentRenderPipeline)
    2. {
    3.    if (GraphicsSettings.currentRenderPipeline.GetType().ToString().Contains("HighDefinition"))
    4.    {
    5.       Debug.Log("HDRP active");
    6.    }
    7.    else // assuming here we only have HDRP or URP options here
    8.    {
    9.       Debug.Log("URP active");
    10.    }
    11. }
    12. else
    13. {
    14.    Debug.Log("Built-in RP active");
    15. }
    16.  
    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:
    https://github.com/0lento/OcclusionProbes/blob/package/OcclusionProbes/OcclusionProbes.asmdef
    (you can just substitute that with whatever package you want)

    More info about asmdef's here: https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html
     
    Last edited: Oct 23, 2020
    NotaNaN, david-mal and EirikWahl like this.
  12. NikiWalker

    NikiWalker

    Unity Technologies

    Joined:
    May 18, 2021
    Posts:
    316
    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:

        "versionDefines": [
    {
    "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:

    Code (CSharp):
    1.         static string GetUnlitShader()
    2.         {
    3. #if USING_URP
    4.             return "Universal Render Pipeline/Unlit";
    5. #elif USING_HDRP
    6.             return "HDRP/Unlit";
    7. #else
    8.             return "Unlit/Color";
    9. #endif
    10.         }
    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).
     
    Last edited: Mar 8, 2022
  13. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    Exactly what I was hoping to find. Thank you.
     
  14. Radivarig

    Radivarig

    Joined:
    May 15, 2013
    Posts:
    121
  15. cdr9042

    cdr9042

    Joined:
    Apr 22, 2018
    Posts:
    173
    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?
     
  16. NikiWalker

    NikiWalker

    Unity Technologies

    Joined:
    May 18, 2021
    Posts:
    316
    Unfortunately yes. I'll ask around about whether or not this is being improved.
     
  17. damian_pablo_gonzalez

    damian_pablo_gonzalez

    Joined:
    Jan 3, 2018
    Posts:
    15
    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.

    Code (CSharp):
    1.             //destroy some components to obtain a simplified version of the object
    2. #if USING_URP
    3.             foreach (UniversalAdditionalCameraData cam in clone.GetComponentsInChildren<UniversalAdditionalCameraData>()) Destroy(cam);
    4. #endif
    5.             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.
     
  18. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    Perhaps this might be of use in your situation?

    https://github.com/Unity-Technologies/ConditionalCompilationUtility

    I can't say for sure, but it might. Worth a try, at least.
     
    Last edited: Sep 25, 2023
  19. NikiWalker

    NikiWalker

    Unity Technologies

    Joined:
    May 18, 2021
    Posts:
    316
    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.
     
    damian_pablo_gonzalez likes this.
  20. test_unity970

    test_unity970

    Joined:
    Sep 27, 2023
    Posts:
    1
    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:
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4.  
    5. public class SRPDetector : EditorWindow
    6. {
    7.     [MenuItem("Tools/Detect SRP")]
    8.     static void DetectSRP()
    9.     {
    10.         // Check if the active rendering path is set to Scriptable Render Pipeline
    11.         if (GraphicsSettings.renderPipelineAsset != null)
    12.         {
    13.             Debug.Log("Using a Scriptable Render Pipeline (HDRP/LWRP/URP)");
    14.             if (GraphicsSettings.renderPipelineAsset is HDRenderPipelineAsset)
    15.             {
    16.                 Debug.Log("High Definition Render Pipeline (HDRP) is being used.");
    17.             }
    18.             else if (GraphicsSettings.renderPipelineAsset is UniversalRenderPipelineAsset)
    19.             {
    20.                 Debug.Log("Universal Render Pipeline (URP) is being used.");
    21.             }
    22.             // Add more checks for other SRPs as needed
    23.         }
    24.         else
    25.         {
    26.             Debug.Log("Using Built-in (Legacy) Render Pipeline");
    27.         }
    28.     }
    29. }
    30.  
    In this script:

    1. 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).

    2. 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.

    3. If no SRP is assigned, it means you are using the Built-in (Legacy) Render Pipeline.
     
    codestage likes this.
  21. codestage

    codestage

    Joined:
    Jul 27, 2012
    Posts:
    1,931
    GraphicsSettings.renderPipelineAsset
    was deprecated, so now you can use the GraphicsSettings.defaultRenderPipeline instead.

    Works great for me both in Editor and Runtime to detect built-in RP.
     
  22. LaserRock

    LaserRock

    Joined:
    Jan 2, 2018
    Posts:
    13
    If you don't have URP or HDRP You can't check the type but it's possible to compare name of type.
    Code (CSharp):
    1.  if (GraphicsSettings.defaultRenderPipeline != null)
    2.             {
    3.                 if (GraphicsSettings.defaultRenderPipeline.GetType().Name == "HDRenderPipelineAsset")
    4.                 {
    5.                     Debug.Log("High Definition Render Pipeline (HDRP) is being used.");
    6.                 }
    7.                 else if (GraphicsSettings.defaultRenderPipeline.GetType().Name == "UniversalRenderPipelineAsset")
    8.                 {
    9.                     Debug.Log("Universal Render Pipeline (URP) is being used.");
    10.                 }
    11.             }
    12.             else
    13.             {
    14.                 Debug.Log("Using Built-in (Legacy) Render Pipeline");
    15.             }