Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Trying To Update A Postprocessing Vignette At Runtime Using The CinemachineVolumeSettings Component

Discussion in 'Cinemachine' started by Sun_Suite, Feb 28, 2023.

  1. Sun_Suite

    Sun_Suite

    Joined:
    Mar 8, 2017
    Posts:
    18
    I'm currently trying to update the look of my post processing vignette at runtime. The code I've posted below seems to be able to update the value, at least in the inspector anyway when ChangeVingetteSize() is triggered, but nothing actually happens in game. If I remove this code and then change the values vignettes center in the inspector manually, then the vignette moves as expected. Has anyone else encountered this? Am I just attempting to change the value in the wrong way / place?

    Code (CSharp):
    1. // Grabbing a reference
    2.     public void GrabVignetteReference()
    3.     {
    4.         caveVolume = FindObjectOfType<CinemachineVolumeSettings>();
    5.  
    6.         if (caveVolume.m_Profile.TryGet<Vignette>(out Vignette vingette))
    7.         {
    8.             currentVingette = vingette;
    9.         }
    10.     }
    11.  
    12.     public void ChangeVignetteSize()
    13.     {
    14.         Debug.Log("Started changing the vignette size");
    15.         Vector2 rawUpdatedVectorValue = new Vector2(0.75f, 2.75f);
    16.         Vector2Parameter newVignetteValue = new Vector2Parameter(rawUpdatedVectorValue, true);
    17.        
    18.          currentVingette.center = newVignetteValue;
    19.     }
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,567
    You're not supposed to dynamically change profile values, as profiles are assets that are supposed to be constant at runtime. The preferred approach is to have multiple profiles with fixed values set to the "extremes" of what you need, and to animate the profile weights to blend between them.

    You could do this with global volumes instead of attaching them to a specific CinemachineCamera. The global profiles will combine with any other profile settings in the vcam.

    If for some reason it's not possible to predefine the extremes (e.g. you want the vignette to be positioned over a target whose position is determined only at runtime), then the approach would be to make a dynamic in-memory profile and modify that at runtime. CinemachineVolumeSettings.cs does something like that to implement focus tracking.
     
    Last edited: Mar 2, 2023
  3. Sun_Suite

    Sun_Suite

    Joined:
    Mar 8, 2017
    Posts:
    18
    Hi Gregoryl,

    Thanks for your response, I'll add some context to make things easier. I'm attempting to implement your second suggestion, regarding creating a volume profile at runtime. Below is my updated script. I originally was attempting to do this on my StateDrivenCamera, but encountered an error that informed me that a CinemachineVirtualCamera component was required on the objects I was making changes too (CinemachineExtention.cs: line 64).

    I've now refactored the code to find my four CinemachineVirtualCamera's, then I assign the new Volume profile I generate at runtime. I seem to be able to set my starting values fine, but as soon as I reach the tweens none of the changes are reflected in game, the values in the inspector are tweened to the desired values (I can see this happening in the inspector) but the games vignette doesn't move. Same as before, If I then change a value in the inspector, whatever event is fired as a result updates the game to reflect the values being shown in the inspector.

    The function I've included below is being called inside of OnSceneLoaded()

    Fairly certain I must have done something wrong here. Any further help would be appreciated.

    Code (CSharp):
    1. public void SetupVignetteAndTween()
    2.     {
    3.         // Creating a volume profile dynamically, so we can update it at runtime
    4.         dynamicPostProcessingVolumeProfile = ScriptableObject.CreateInstance<VolumeProfile>();
    5.  
    6.         // Finding all the cinemachine virtual cameras in the scene
    7.         cinemachineVirtualCameras = FindObjectsOfType<CinemachineVirtualCamera>();
    8.  
    9.         // Removes any cameras from previous scenes
    10.         if(allCinemachineVirtualCameras.Count > 0)
    11.         {
    12.             allCinemachineVirtualCameras.Clear();
    13.         }
    14.    
    15.         // Taking the array of cinemachine virtual cameras and creating a list from that array - to make them easier to work with
    16.         foreach (CinemachineVirtualCamera camera in cinemachineVirtualCameras)
    17.         {
    18.             allCinemachineVirtualCameras.Add(camera);
    19.         }
    20.  
    21.         // Adding a vignette override to the post processing volume we just created
    22.         dynamicPostProcessingVolumeProfile.Add<Vignette>(true);
    23.  
    24.         // Assigning the dynamically created volume profile to each virtual camera
    25.         foreach (CinemachineVirtualCamera camera in allCinemachineVirtualCameras)
    26.         {
    27.             if (camera.TryGetComponent<CinemachineVolumeSettings>(out CinemachineVolumeSettings cinemachineVolumeSettings))
    28.             {
    29.                 cinemachineVolumeSettings.m_Profile = dynamicPostProcessingVolumeProfile;
    30.                 Debug.Log("Vignette profile was assigned to a virtual camera");
    31.             }
    32.         }
    33.  
    34.         if (dynamicPostProcessingVolumeProfile.TryGet<Vignette>(out vignette)) {
    35.  
    36.             // Setting the starting values
    37.             rawUpdatedVectorValue = new Vector2(0.5f, 0.5f);
    38.             vignette.center.overrideState = true;
    39.             newVignetteValue = new Vector2Parameter(rawUpdatedVectorValue, true);
    40.  
    41.             rawUpdatedIntensityValue = 1f;
    42.             newIntensityValue = new ClampedFloatParameter(rawUpdatedIntensityValue, 0f, 1f, true);
    43.             vignette.intensity.overrideState = true;
    44.             vignette.intensity.value = newIntensityValue.value;
    45.  
    46.             rawUpdatedSmoothnessValue = 1f;
    47.             newSmoothnessValue = new ClampedFloatParameter(rawUpdatedSmoothnessValue, 0f, 1f, true);
    48.             vignette.smoothness.overrideState = true;
    49.             vignette.smoothness.value = newSmoothnessValue.value;
    50.  
    51.             // Rounding the edges of the vignette
    52.             newRoundedValue = new BoolParameter(rawRoundedValue, true);
    53.             vignette.rounded.value = newRoundedValue.value;
    54.  
    55.             dynamicPostProcessingVolumeProfile.Reset();
    56.  
    57.             DOVirtual.Float(1f, vignetteIntensityTarget, vignetteTimeToExpand, newValue =>
    58.             {
    59.                 vignette.intensity.overrideState = true;
    60.                 vignette.intensity.value = new ClampedFloatParameter(newValue, 0f, 1f, true).value;
    61.                 dynamicPostProcessingVolumeProfile.Reset();
    62.             }).SetEase(Ease.InExpo);
    63.  
    64.             DOVirtual.Float(1f, vignetteSmoothnessTarget, vignetteTimeToExpand, newValue =>
    65.             {
    66.                 vignette.smoothness.overrideState = true;
    67.                 vignette.smoothness.value = new ClampedFloatParameter(newValue, 0f, 1f, true).value;
    68.                 dynamicPostProcessingVolumeProfile.Reset();
    69.             }).SetEase(Ease.InExpo);
    70.         }
    71.     }
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,567
    Sorry for the slow response. Have you solved this issue yet?

    My sense is that you're going about this the hard way. Why don't you have a single global dynamic volume that you enable when needed? No reason to involve the CinemachineCameras at all.
     
  5. Sun_Suite

    Sun_Suite

    Joined:
    Mar 8, 2017
    Posts:
    18
    Hi Gregoryl,

    I did manage to solve it in the end. I set the Focus tracking to "None" on my virtual cameras and it all started working as expected. Beforehand, I had it set to "Follow Target". I'm now just using the animated target option on the State Camera. As for why that worked, couldn't tell you I'm afraid.