VFX graph spawn/capacity scaling based on quality?

In ShaderGraph, we have access to the current Quality the game is running at, which can can use with branch nodes to change the behavior of the shader based on the current game quality.

I was wondering if anything similar existed in ShaderGraph? Ideally, if someone’s running with the highest graphics settings, a given VFX would have a higher spawn rate and capacity. Lower end systems would cap the effects at a more manageable amount.

I know that I can configure each of my VFX Graph objects individually to pass in a parameter, and set that based on quality. But before I make a sweeping change like that, I wanted to confirm A) Is there anything built-in to handle that for me, and B) Would it really make much difference? (It’s hard to judge just how much of a performance impact comes from doubling the spawn rate, for example, or whether that’s a drop in the bucket compared to just having the VFX graph exist in the first place.)

You’re correct, we don’t have access to the current Quality of the game is running at in VFX Graph.
Now you can create a setup with some expose property.

Here I have created an exposed property Uint called “Quality Setting”.


I’ve also set the mode to “Enum” to be able to set “Name” to the values.

Now I can use this Enum value to drive the behavior of my particles, their count etc…
Here are some examples:

Driving the particle Spawn Count:

The spawn rate is modulated based on the Enum value (0= High Fidelity, 1= Balanced, 2= Performant)

Note that as you cannot change dynamically the capacity size, you’ll need to allocate for the Highest scenario. Based on the context, targeted platform etc., this isn’t always the best. It’s often better to have a capacity that is closed to the max number of particles. But if the delta between the quality settings isn’t too high, it could be fine.

Changing Block values based on Quality Setting:


Some block setting can influence performances, like the number of Octaves when using Noise/Turbulence.

Enable/disable Block based on Condition:


In this example, the Collision Shape Plane Block in deactivated when the Quality setting is set to performant.

Swapping Meshes based on the Quality Setting:
By setting the MeshCount to 3, I’m able to set three different Mesh. With this, I can choose which mesh to render based on the quality setting Enum. For this, we need to set the Mesh Index attribute value.

With these examples, let’s see how to link our exposed property with the Quality setting of our project:

First I create a MonoBehaviour Script called SetVFXQualitySetting attached to our VFX in the scene:

Here is the code with comments that set the value of our Exposed property (“Quality Setting”) with the our Project’s current quality setting.

using UnityEngine;
using UnityEngine.VFX;
using UnityEngine.VFX.Utility;

[ExecuteInEditMode]
public class SetVFXQualityLevel : MonoBehaviour
{
    private VisualEffect m_VFX;
    private ExposedProperty m_QualitySettingProperty;

    private void OnEnable()
    {
        //Set the m_VFX variable with the VFX instance.
        m_VFX = GetComponent<VisualEffect>();
        //Set the Exposed property name with the same name as the VFX Graph exposed property.
        m_QualitySettingProperty = "Quality Setting";
        
        //Subscribe to the activeQualityLevelChanged Event 
        QualitySettings.activeQualityLevelChanged += QualitySettings_activeQualityLevelChanged;

    }
    
    private void QualitySettings_activeQualityLevelChanged(int previousQuality, int currentQuality)
    {
        //Check if the "Quality Setting" property exist on our VFX instance.
        if (m_VFX.HasUInt(m_QualitySettingProperty))
        {
            //Set the Quality Setting value of our VFX with the project current Quality setting value.
            m_VFX.SetUInt(m_QualitySettingProperty, (uint)currentQuality);
        }
        
        //Debug.Log the Previous and Current Quality Setting.
        //Debug.Log($"Quality Level has been changed from {QualitySettings.names[previousQuality]} to {QualitySettings.names[currentQuality]}");
    }
    
    // Unsubscribe to the Event.
    void OnDestroy()
    {
        QualitySettings.activeQualityLevelChanged -= QualitySettings_activeQualityLevelChanged;
    }
}

With this, everything should be working and update upon quality setting change:

Unity_jnbIxcnm9U
Unity_sCQbbRPnoJ

Now does it matter?
It’s very difficult to tell as this depends on your VFX, the Targeted platform and what you’re actually doing with your Quality setting. As always, the key is to make an informed decision based on your knowledge of the target platform. Run performance captures on your target platforms and try to identify your bottlenecks.

I’m sorry to come with such an answer, but I didn’t see how to answer with a Yes-No.
I wish you a warm day.

1 Like

Thanks for such a detailed reply. It’s too bad the parameter needs to be manually set, but as long as I pick a consistent property name, this isn’t really a big deal. The other details here were very interesting, specifically choosing a different mesh based on quality. Thanks again for giving me plenty to work with here.

With pleasure. I really would like VFX Graph to have more built-in options regarding scalability/quality settings. I hope that will be able to provide something in the future