1 # Manipulating the Stack
5 While working on a game you'll often need to push effect overrides on the stack for time-based events or temporary states. You could dynamically create a global volume on the scene, create a profile, create a few overrides, put them into the profile and assign the profile to the volume but that's not very practical.
7 We provide a `QuickVolume` method to quickly spawn new volumes in the scene:
10 public PostProcessVolume QuickVolume(int layer, float priority, params PostProcessEffectSettings[] settings)
13 First two parameters are self-explanatory. The last parameter takes an array or a list of effects you want to override in this volume.
15 Instancing a new effect is fairly straightforward. For instance, to create a Vignette effect and override its enabled & intensity fields:
18 var vignette = ScriptableObject.CreateInstance<Vignette>();
19 vignette.enabled.Override(true);
20 vignette.intensity.Override(1f);
23 Now let's look at a slightly more complex effect. We want to create a pulsating vignette effect entirely from script:
27 using UnityEngine.Rendering.PostProcessing;
29 public class VignettePulse : MonoBehaviour
31 PostProcessVolume m_Volume;
36 m_Vignette = ScriptableObject.CreateInstance<Vignette>();
37 m_Vignette.enabled.Override(true);
38 m_Vignette.intensity.Override(1f);
40 m_Volume = PostProcessManager.instance.QuickVolume(gameObject.layer, 100f, m_Vignette);
45 m_Vignette.intensity.value = Mathf.Sin(Time.realtimeSinceStartup);
50 RuntimeUtilities.DestroyVolume(m_Volume, true, true);
55 This code creates a new vignette and assign it to a newly spawned volume with a priority of `100`. Then, on every frame, it changes the vignette intensity using a sinus curve.
57 > **Important:** Don't forget to destroy the volume and the attached profile when you don't need them anymore!
61 Distance-based volume blending is great for most level design use-cases, but once in a while you'll want to trigger a fade in and/or out effect based on a gameplay event. You could do it manually in an `Update` method as described in the previous section or you could use a tweening library to do all the hard work for you. A few of these are available for Unity for free, like [DOTween](http://dotween.demigiant.com/), [iTween](http://www.pixelplacement.com/itween/index.php) or [LeanTween](https://github.com/dentedpixel/LeanTween).
63 Let's use DOTween for this example. We won't go into details about it (it already has a good [documentation](http://dotween.demigiant.com/documentation.php)) but this should get you started:
67 using UnityEngine.Rendering.PostProcessing;
70 public class VignettePulse : MonoBehaviour
74 var vignette = ScriptableObject.CreateInstance<Vignette>();
75 vignette.enabled.Override(true);
76 vignette.intensity.Override(1f);
78 var volume = PostProcessManager.instance.QuickVolume(gameObject.layer, 100f, vignette);
82 .Append(DOTween.To(() => volume.weight, x => volume.weight = x, 1f, 1f))
84 .Append(DOTween.To(() => volume.weight, x => volume.weight = x, 0f, 1f))
87 RuntimeUtilities.DestroyVolume(volume, true, true);
94 In this example, like the previous one, we spawn a quick volume with a vignette. We set its `weight`property to `0` as we don't want it to have any contribution just yet.
96 Then we use the sequencing feature of DOTween to chain a set of tweening events: fade in, pause for a second, fade out and finally destroy the volume and the component itself once it's done.
98 And that's it. Of course you can also tween individual effect properties instead of the volume as a whole, it's up to you.
102 You can also manually edit an existing profile on a volume. It's very similar to how material scripting works in Unity. There are two ways of doing that: either by modifying the shared profile directly or by requesting a clone of the shared profile that will only be used for this volume.
104 Each method comes with a a few advantages and downsides:
106 - Shared profile editing:
107 - Changes will be applied to all volumes using the same profile
108 - Modifies the actual asset and won't be reset when you exit play mode
109 - Field name: `sharedProfile`
110 - Owned profile editing:
111 - Changes will only be applied to the specified volume
112 - Resets when you exit play mode
113 - It is your responsibility to destroy the profile when you don't need it anymore
114 - Field name: `profile`
116 The `PostProcessProfile` class has a few utility methods to help you manage assigned effects. Notable ones include:
118 - `T AddSettings<T>()`: creates, adds and returns a new effect or type `T` to the profile. Will throw an exception if it already exists.
119 - `PostProcessEffectSettings AddSettings(PostProcessEffectSettings effect)`: adds and returns an effect you created yourself to the profile.
120 - `void RemoveSettings<T>()`: removes an effect from the profile. Will throw an exception if it doesn't exist.
121 - `bool TryGetSettings<T>(out T outSetting)`: gets an effect from the profile, returns `true` if one was found, `false` otherwise.
123 You'll find more methods by browsing the `/PostProcessing/Runtime/PostProcessProfile.cs` source file.
125 > **Important:** Don't forget to destroy any manually created profiles or effects.
129 If you need to instantiate `PostProcessLayer` at runtime you'll need to make sure resources are properly bound to it. After the component has been added, don't forget to call `Init()` on it with a reference to the `PostProcessResources` file as a parameter.
132 var postProcessLayer = gameObject.AddComponent<PostProcessLayer>();
133 postProcessLayer.Init(resources);