Search Unity

URP / Volume.cs - how to access the override settings at runtime via script?

Discussion in 'Universal Render Pipeline' started by zapposh, Jan 21, 2020.

  1. zapposh

    zapposh

    Joined:
    Nov 12, 2016
    Posts:
    117
    I'm using 2019.3.0f5 with URP (2D pixel perfect renderer) and volume.cs for adding post-processing effects to my scene.

    How can I access the override settings of the PP-profile at runtime via script?
    I have searched everywhere for documentation, and while there is quite a bit on volume-layers and LWRP, I cannot find the correct procedures using URP with volume.cs.

    Let's say I want to change the bloom intensity at runtime every time the player takes damage.
    Any ideas? Thanks.
     
    Blue-Wolf likes this.
  2. Blue-Wolf

    Blue-Wolf

    Joined:
    May 27, 2014
    Posts:
    20
    I've been looking all over for this too and was just about to make a similar post. If anyone can provide some guidance it would be great!
     
    zapposh likes this.
  3. Arfus

    Arfus

    Joined:
    Mar 12, 2013
    Posts:
    29
    Personally I'm using the following approach.

    I get a reference to the Volume component either in runtime or by assigning it in editor.
    Once I have a reference, to the volume component I can simply use the following code to get a reference to a VolumeComponent.


    Code (CSharp):
    1. UnityEngine.Rendering.VolumeProfile volumeProfile = GetComponent<UnityEngine.Rendering.Volume>()?.profile;
    2. if(!volumeProfile) throw new System.NullReferenceException(nameof(UnityEngine.Rendering.VolumeProfile));
    3.  
    4. // You can leave this variable out of your function, so you can reuse it throughout your class.
    5. UnityEngine.Rendering.Universal.Vignette vignette;
    6.  
    7. if(!volumeProfile.TryGet(out vignette)) throw new System.NullReferenceException(nameof(vignette));
    8.  
    9. vignette.intensity.Override(0.5f);
    You can cache the VolumeComponent, so you only need to retrieve it once (for example in your Awake).

    Edit: Added the appropriate namespaces to VolumeProfile and Volume. Also added a comment for a bit more clarity.
     
    Last edited: Mar 12, 2020
  4. zapposh

    zapposh

    Joined:
    Nov 12, 2016
    Posts:
    117
    Wonderful solution, works like a charm. Many thanks!
     
  5. Blue-Wolf

    Blue-Wolf

    Joined:
    May 27, 2014
    Posts:
    20
    Cheers Arfus!

    For anyone who ran into a similar issue, I was using "UnityEngine.Rendering.PostProcessing" instead of "UnityEngine.Rendering.Universal" for effects like Vignette, hence volumeProfile.TryGet() wasn't working. I needed to use the latter for URP, as Arfus' answer shows.
     
  6. Arfus

    Arfus

    Joined:
    Mar 12, 2013
    Posts:
    29
    Np! And yes, my exact solution was an implementation for URP. That's the implementation I gave as that's the title of the original post ;)

    Edit: Although, if I recall correctly, the approach for the Post Processing Stack V2 is quite similar to this. But I do not have a code sample for that.
     
  7. Blue-Wolf

    Blue-Wolf

    Joined:
    May 27, 2014
    Posts:
    20
    Ah, I wasn't clear, the URP solution is what I was looking for. I didn't know that UnityEngine.Rendering.PostProcessing didn't work with URP post-processing until I saw your answer. Thanks for clearly pointing out the correct namespace in your answer!
     
    KMDeclius and Arfus like this.
  8. Arfus

    Arfus

    Joined:
    Mar 12, 2013
    Posts:
    29
    Np, glad it works for you :)
     
    Blue-Wolf likes this.
  9. zapselon

    zapselon

    Joined:
    Jun 16, 2020
    Posts:
    1
    I can't find my profile and it throws all those null reference errors, can you help?
    Edit: i meant that the script isn't accessing my profile (maybe because i have multiple) so in the first line itself is there an elaborative way i can access it?
     
    Last edited: Aug 2, 2020
  10. Arfus

    Arfus

    Joined:
    Mar 12, 2013
    Posts:
    29
    You need to attach the component you created containing my code, onto the SAME gameobject as the Volume component. If you read the code, you can see I make use of GetComponent. This only works when attached onto the same gameobject.
     
  11. marcanthonysanti

    marcanthonysanti

    Joined:
    Jul 28, 2020
    Posts:
    3
    This worked great, thank you!
     
  12. trantak

    trantak

    Joined:
    Jan 9, 2014
    Posts:
    3
    Thank you! Finally found something that works
     
  13. Stephaniecheng14

    Stephaniecheng14

    Joined:
    Sep 15, 2020
    Posts:
    2
    I've been searching everywhere for this solution! Finally something that actually works! Thank you!!!!
     
  14. jgarbeidi

    jgarbeidi

    Joined:
    Apr 2, 2014
    Posts:
    3
    This was a godsend, I was accessing it completely wrongly, but now that I know how it's trivial! Gonna put this to good use on the options screen.
     
  15. Velvara

    Velvara

    Joined:
    Nov 30, 2020
    Posts:
    1
    I am trying to modify the Weight value of the volume and I've tried this approach, but it only works to affect the profiles within. do you know how to access just the Weight value in the volume?
    It seems simple, but there doesn't seem to be a Weight value inside the Volume (despite the documentation saying it does) and it's driving me nuts @_@

    Code (CSharp):
    1. var volume = gameObject.GetComponent<Volume>();
    2.  
    3. volume.weight(<<<this weight does not exist!!!)
     
  16. duartejuca

    duartejuca

    Joined:
    Aug 23, 2018
    Posts:
    13

    Thank you!!
     
  17. vmsgrg

    vmsgrg

    Joined:
    Aug 29, 2018
    Posts:
    4
    Is there any way to modify postExposure value on Volume in runtime?
     
  18. StealthMode_JW

    StealthMode_JW

    Joined:
    Jul 10, 2015
    Posts:
    3
    Thanks for this, Arfus! I, like many others, have been searching all over for this.

    I'm wondering if you can help me though. I'm only able to grab the Override at Start(), but somehow lose the reference when I need it later on. In my case, I'm grabbing the LensDistortion Override. I test it at Start() and can see it works. But when the Coroutine is called where I actually manipulate the LensDistortion, I get a Null reference exception.
    I tested all three: I'm getting Null Ref Exceptions for the LensDistortion, the VolumeProfile, all the way back to the Volume itself...even though the Inspector acknowledges the reference to the correct GameObject.

    Code (CSharp):
    1. public UnityEngine.Rendering.Volume volume;         //just using this for testing
    2.     public UnityEngine.Rendering.VolumeProfile volumeProfile;
    3.     public UnityEngine.Rendering.Universal.LensDistortion lensDistortion;
    4.  
    5.     void Start()
    6.     {
    7.         volume = GetComponent<Volume>();
    8.         if (!volume) throw new System.NullReferenceException(nameof(UnityEngine.Rendering.Volume));
    9.  
    10.         volumeProfile = GetComponent<UnityEngine.Rendering.Volume>()?.profile;
    11.         if (!volumeProfile) throw new System.NullReferenceException(nameof(UnityEngine.Rendering.VolumeProfile));
    12.  
    13.         if (!volumeProfile.TryGet(out lensDistortion)) throw new System.NullReferenceException(nameof(lensDistortion));
    14.        
    15.         lensDistortion.intensity.Override(0.5f);
    16.     }
    17.  
    18.     public IEnumerator TimeWarpRoutine()
    19.     {
    20.         lensDistortion.intensity.Override(0.0f);  
    21.  
     
  19. StealthMode_JW

    StealthMode_JW

    Joined:
    Jul 10, 2015
    Posts:
    3
    FIX: I finally figured this out.

    A quick recap: I was using Post-Processing to set up a few effects. I decided to add URP, which renders Post-Processing useless. I still had a Post-Processing GameObject (that was turned off) in case URP wasn't going to work for me. And then I was running into the above problems (hindsight is 20/20)...

    I considered other comments / threads' suggestions of removing Post-Processing and URP and reinstalling URP. In my case, I noticed a warning (not error) in my Console that something was trying to access my Post-Processing Volume but couldn't find it. There was no specific stack-trace to follow so I did a solution-wide search for the term "Post-Processing" and couldn't find any of my scripts trying to access that Post-Processing Volume. This is when I determined something on the Unity side might be trying to access my post-processing volume based on default settings when it was originally installed. I relented that I may have to remove both packages and re-install URP; though I was worried about having to set up the Global Volume again and make sure it was all done correctly, because clearly that side of it was working at Start() but somehow I was losing the reference to the Global Volume sometime during Runtime.

    This is what I actually did: I removed the Post-Processing Volume. That's it. I tested it again and it worked. Clearly, Unity was still trying to access it based on default settings. I didn't have to remove and reinstall URP. That was my case. I hope this helps somebody who was having additional issues like I was.

    Thanks again to Arfus for the original solution for accessing Overrides while using URP.
     
  20. Cenly

    Cenly

    Joined:
    May 30, 2022
    Posts:
    16
    THAKN YOU so much!!!! Dont know the principle yet, but adding ".Override" took effect!!! Searching for hours and finally resolved I'm soooo happy...
     
  21. unity_CF14CD16A64ADE413915

    unity_CF14CD16A64ADE413915

    Joined:
    Sep 11, 2022
    Posts:
    4

    You are a Lengend
     
  22. Chico27

    Chico27

    Joined:
    Aug 13, 2023
    Posts:
    1
    Having a hard time converting this PostProcessVolume to Volume. Cause im working on URP. Can someone help me? I cant get into properties of Volume component.

    public float intensity = 0;

    PostProcessVolume _volume;
    Vignette _vignette;

    // Start is called before the first frame update
    void Start()
    {


    _volume = GetComponent<PostProcessVolume>();
    _volume.profile.TryGetSettings<Vignette>(out _vignette);

    if (!_vignette)
    {
    print("error, vignette empty");
    }

    else
    {
    _vignette.enabled.Override(false);
    }
    }

    // Update is called once per frame
    void Update()
    {
    if (Input.GetMouseButtonDown(0))
    StartCoroutine(TakeDamageEffect());
    }

    private IEnumerator TakeDamageEffect()
    {
    intensity = 0.4f;

    _vignette.enabled.Override(true);
    _vignette.intensity.Override(0.4f);

    yield return new WaitForSeconds(0.4f);

    while (intensity > 0)
    {
    intensity -= 0.01f;
    if (intensity < 0) intensity = 0;
    _vignette.intensity.Override(intensity);
    yield return new WaitForSeconds(0.1f);
    }

    _vignette.enabled.Override(false);
    yield break;
    }
     
  23. WhyCantIUseMyLogin

    WhyCantIUseMyLogin

    Joined:
    Oct 1, 2013
    Posts:
    14
    This is probably a bit late to help Chico27 but since I was struggling with the same problem, I thought I would post this in case anyone else stumbles their way here as I did.

    Chico27 and I were going wrong by using a code sample for the Built-In render pipeline rather than the URP scriptable render pipeline, so below is a tiny sample for URP:

    In this example I have a gameobject in the scene called PostProcessVolume, which has a component of type Volume with a Depth of Field override added.


    Code (CSharp):
    1. using UnityEngine.Rendering;
    2. using UnityEngine.Rendering.Universal;
    3.  
    4. public class Foo: MonoBehaviour
    5. {
    6.     Volume _postProcessVolume;
    7.     DepthOfField _ppDepthOfField;
    8.  
    9.     void Awake()
    10.     {
    11.         _postProcessVolume = GameObject.Find("PostProcessVolume").GetComponent<Volume>();
    12.         _postProcessVolume.profile.TryGet(out _ppDepthOfField);
    13.     }
    14.  
    15.     internal void SetDOF(bool b)
    16.     {
    17.         _ppDepthOfField.active = b;
    18.     }
    19. }