Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to get access to renderer features at runtime?

Discussion in 'Universal Render Pipeline' started by Twin-Stick, Nov 5, 2021.

  1. Twin-Stick

    Twin-Stick

    Joined:
    Mar 9, 2016
    Posts:
    111
    Hey all,
    Could someone please shed some light how I would get access to a renderer feature at runtime?

    Previously I had linked the asset directly with a serialized field, but now I have put the asset into bundles with addressables, this simply creates an instance of it rather than the current asset in use.

    Many thanks!

    **EDIT**
    I've managed to find a way to get this done via reflection to access the private property (why are the renderer features private?) Is there a way to do this without hacking it?

    Code (CSharp):
    1. var renderer = (GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset).GetRenderer(0);
    2.         var property = typeof(ScriptableRenderer).GetProperty("rendererFeatures", BindingFlags.NonPublic | BindingFlags.Instance);
    3.  
    4.         List<ScriptableRendererFeature> features = property.GetValue(renderer) as List<ScriptableRendererFeature>;
    Property found via documentation here -> https://docs.unity3d.com/Packages/c...Universal_ScriptableRenderer_rendererFeatures
     
    Last edited: Nov 6, 2021
  2. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    ScriptableRenderFeatures are ScriptableObjects, and would be serialized as an asset. You should simply be able to reference that asset directly and skip the reflection all together.
     
  3. Twin-Stick

    Twin-Stick

    Joined:
    Mar 9, 2016
    Posts:
    111
    Yup, and that's exactly what I was doing prior to them being bundled with addressables.
    When I bundled them, the serialised link wouldn't point to the instance in memory, so it would create a new instance of it, and any changes had no effect. ‍♂️
     
  4. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    I'm doing the reflection hack too. Just wait until you want to modify the settings of any of those at runtime (eg SSAO).I understand the purpose of making things internal if those things actually are internal, but if you can modify them in the editor, then they're not really internal anymore are they?

    My guess as to why it's internal is "corporate politics" although it's purely speculation. Every exposed property requires documentation in multiple languages (English and Chinese at a minimum) and maybe additional code reviews. And if they add something late in a dev cycle, there might not be time to send it off o the documentation teams.
     
    Twin-Stick likes this.
  5. Twin-Stick

    Twin-Stick

    Joined:
    Mar 9, 2016
    Posts:
    111
    Yeah that sounds reasonable, especially the documentation Side of things.
     
  6. equalsequals

    equalsequals

    Joined:
    Sep 27, 2010
    Posts:
    154
    Ah yes, that's my fault for not reading fully. Apologies.

    Thought: you could have the renderer feature implement something like a singleton pattern, or perhaps place itself into a statically held array. The asset itself could store the index it's placed at. Then, instead of storing the renderer features asset itself as an addressable, have a 'token' ScriptableObject which maps to the same ID.

    This is all just a workaround of course, but seems less hacky than Reflection. It's also a pattern that could applied more broadly to work around this quirk.
     
  7. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254

    Plausible, yes. Reasonable... well it's been more than a year and accessing custom Render Features to adjust their parms at runtime is still troublesome.

    Ona related note, are you keeping a reference to each quality levels' render assets and just sniffing the current quality level. each time you need to make a change?
     
  8. HajiyevEl

    HajiyevEl

    Joined:
    Feb 19, 2020
    Posts:
    41
    Thank you, helped me a lot.

    Code (CSharp):
    1.             var renderer = (GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset).GetRenderer(0);
    2.             var property = typeof(ScriptableRenderer).GetProperty("rendererFeatures", BindingFlags.NonPublic | BindingFlags.Instance);
    3.  
    4.             List<ScriptableRendererFeature> features = property.GetValue(renderer) as List<ScriptableRendererFeature>;
    5.  
    6.             foreach (var feature in features)
    7.             {
    8.                 if (feature.GetType() == typeof(BlurKawaseURP))
    9.                 {
    10.                     (feature as BlurKawaseURP).Settings.downsample = 4;
    11.                 }
    12.             }
     
  9. legostarwars511

    legostarwars511

    Joined:
    Aug 9, 2023
    Posts:
    1
    Thanks man, it just worked after some little modifications for my usecase. Was scared that I will sit here for weeks to figure it out <3