Scripting Support (C#)

advanced scripting

Global Dirt · Scripting Support (C#)

Everything Global Dirt does is driven by the volume override, so scripting it is the same as scripting any URP volume: get the GlobalDirtVolume component from a profile and change its parameters. All types live in the GlobalDirt namespace.

Fading the effect in and out

using UnityEngine;
using UnityEngine.Rendering;
using GlobalDirt;

public class DirtFader : MonoBehaviour
{
    public Volume volume;

    public void SetDirtIntensity(float amount)
    {
        if (volume.profile.TryGet<GlobalDirtVolume>(out var dirt))
        {
            dirt.intensity.overrideState = true;
            dirt.intensity.value = amount;
        }
    }
}

Intensity at zero disables the effect completely, including all its rendering work, so fading to zero is also the cheapest way to turn it off.

Field names

Every inspector control is a public parameter on GlobalDirtVolume. Set overrideState to true and assign value, exactly like the intensity example. Some fields use a code name that differs from the friendly inspector label:

InspectorField
Dirt StrengthdirtAmount
Dirt SizedirtPatchSize
Dirt Under CoverdirtProtectedPreference
Dirt Thickness / Thickness Max DistancedirtRelief / dirtReliefDistance
Dust StrengthdustAmount
Dust Top BiasdustTopPreference
Dust Settle Max DistancedustSettleDistance
Dust CracksdustCracks
Moss StrengthgrowthAmount
Moss Size / Detail SizegrowthPatchSize / mossDetailSize
Moss Under CovergrowthProtectedPreference
Moss Cracks / Relief / TintmossCracks / growthRelief / mossTint
Moss Relief Max DistancegrowthReliefDistance
Moss Micro Shadows / Shadow Max DistancemossMicroShadows / mossMicroShadowsDistance
Moss Bioluminescence / Glow ColormossBioluminescence / mossBioluminescenceColor
Metal Aging StrengthmetalAgingAmount
Metal Aging Size / Aging TintmetalAgingPatchSize / metalAgingTint
Metal Aging Finish Loss / DiscolorationmetalAgingFinishLoss / metalAgingDiscoloration
Rust StrengthrustAmount
Rust Size / Detail SizerustPatchSize / rustDetailSize
Rust Relief / Relief Max DistancerustRelief / rustReliefDistance
Rust Under CoverrustProtectedPreference
Color Variation Pattern / ContrastmacroVariationPattern / macroVariationContrast
Color Variation Min / MaxmacroVariationMin / macroVariationMax
Color Variation SizevariationSize
Sun BleachsunBleaching
Darken Bottom / Lighten TopverticalGradient / lightenTowardsTop
Rendering Layer FilterexcludedRenderingLayerFilter

The rest read as you would expect: dirtCoverage, dirtColor, dirtColorDense, dirtCracks, dirtSeed, dirtOffset, and the same Coverage, Seed and Offset shape for dust (dust*), moss (growth*), metal aging (metalAging*) and rust (rust*). They are not identical, though: only dirt and dust carry a color pair, moss and rust take a Tint instead, and Cracks exists for dirt, dust and moss. A few more details: compareLineAngle uses radians in code while the inspector shows degrees, metal aging and rust take Strength up to 2 rather than 1, dirtProtectedPreference ranges from -1 to 1, and every Size field and every Max Distance is a MinFloatParameter, clamped at the bottom only.

Seeds and offsets from script

if (volume.profile.TryGet<GlobalDirtVolume>(out var dirt))
{
    // another arrangement of the dirt, same look, different placement
    dirt.dirtSeed.overrideState = true;
    dirt.dirtSeed.value = Random.Range(0, 10000);

    // slide the moss two meters along X
    dirt.growthOffset.overrideState = true;
    dirt.growthOffset.value = new Vector3(2f, 0f, 0f);
}

Zones at runtime

// Give an area of the scene its own settings
var zoneGO = new GameObject("Dirty area");
zoneGO.transform.position = somewhere;
var zone = zoneGO.AddComponent<GlobalDirtZone>();
zoneGO.transform.localScale = new Vector3(12f, 6f, 12f);   // the scale is the size in meters
zone.roundness = 0f;           // 0 is the box, 1 the sphere or ellipsoid inside it
zone.fadeDistance = 3f;
zone.weight = 1f;
zone.priority = 0;
zone.profile = myAreaProfile;   // optional, a Volume Profile with a Global Dirt override
zone.inheritGlobal = true;      // keep the scene look and only apply the overrides

Per object at runtime

GlobalDirtObject carries the three per-object jobs. Adding one from script leaves anchor on, which is what a moving prop wants; set it to false for a profile-only or exclusion-only component.

// Keep dirt attached to a moving prop
myProp.AddComponent<GlobalDirtObject>();

// Keep a character clean, along with every renderer under it
var clean = myCharacter.AddComponent<GlobalDirtObject>();
clean.anchor = false;
clean.excludeFromGlobalDirt = true;
clean.include = GlobalDirtObjectInclude.Children;
clean.Refresh();

// Give one prop its own look
var custom = myProp.AddComponent<GlobalDirtObject>();
custom.anchor = false;
custom.profile = myObjectProfile;
custom.inheritGlobal = true;

// Or drive the renderer set yourself
custom.SetRenderers(myRenderers);

The component registers itself while enabled. Its renderer set is rebuilt on enable, on validate and on hierarchy changes in the editor; at runtime call Refresh() after you change the hierarchy, the layers or the names. SetRenderers() switches Include to Scripting and takes the list as is.

Multiple volumes

Global Dirt follows standard volume blending: put different override values in local volumes and the settings blend as the camera moves between them, priorities and blend distances included. A common setup is a global volume with Intensity zero and a local volume with the dirty look inside a building.

Was this page helpful?