Scripting Support (C#)
advanced scriptingCloud Shadows FX · Scripting Support (C#)
Control Cloud Shadows FX at runtime using the SSCS namespace. The effect is a MonoBehavior component — access it via GetComponent<CloudShadows>() on the GameObject that holds the component.
using SSCS;
CloudShadows cs = GetComponent<CloudShadows>();
cs.profile.coverage = 0.5f;
cs.UpdateMaterialProperties();
CloudShadows
MonoBehavior component that renders cloud shadows and optional volumetric clouds. Add it to any GameObject and assign a CloudShadowsProfile.
General
CloudShadowsProfile profile
Reference to the profile ScriptableObject that defines all cloud and shadow settings.
Light sun
Reference to the directional light used for shadow and cloud lighting calculations. If null, the main directional light is used automatically.
LayerMask cameraLayerMask
Layer mask that determines which cameras receive the cloud shadow effect.
int renderQueue
Render queue for the shadow pass. Clouds render at renderQueue + 1. Default 3001.
Custom Bounds
bool useCustomBounds
Enables limiting cloud shadows to a specific rectangular area instead of the entire scene.
Bounds bounds
The bounding box for custom bounds mode (center + size).
Transform boundsAnchor
Optional anchor transform. When set, the bounds center follows the anchor's XZ position.
Coverage Mask
bool coverageMask
Enables the coverage mask system for painting shadows on/off in specific areas.
Texture2D coverageMaskTexture
The coverage mask texture. Controls where shadows appear.
Vector3 coverageMaskWorldSize
World-space size of the area covered by the mask texture. Default (2000, 0, 2000).
Vector3 coverageMaskWorldCenter
World-space center of the coverage mask area.
bool coverageIncludeClouds
When enabled, the coverage mask also prevents clouds from rendering in masked areas (not just shadows).
Methods
void UpdateMaterialProperties()
Applies all property changes to the cloud shadow material. Call after modifying profile or component properties at runtime.
Bounds GetBounds()
Returns the current effective bounds of the cloud shadow area.
void SetBounds(Bounds bounds)
Sets the bounds of the cloud shadow area and enables custom bounds mode.
void MaskPaint(Vector3 pos, byte value, float brushWidth, float brushOpacity = 1f, float brushFuzziness = 0f)
Paints the coverage mask at a world position. value 0 = remove shadows, 255 = full shadows.
void MaskClear(byte value)
Clears the entire coverage mask to the specified value.
void MaskFillArea(GameObject go, byte value, float opacity = 1f, float border = 0f)
Fills the coverage mask area occupied by the given GameObject's bounds.
void MaskFillArea(MeshRenderer meshRenderer, byte value, float opacity = 1f, float border = 0f)
Fills the coverage mask area using a specific MeshRenderer's bounds.
Shadow Sampling
Reads the cloud shadow on the CPU at any world position, matching what the shader draws on screen. Useful for stealth visibility, plant growth, solar panels or any gameplay that reacts to cloud cover. The CPU copy of the cloud textures is built when the component is enabled and rebuilt only if the textures change.
float SampleShadowAtPosition(Vector3 worldPosition, Camera camera = null)
Amount of cloud shadow at a world position, from 0 (fully lit) to 1 (fully darkened). Pass a camera to also apply the view distance fade used on screen.
CloudShadowSample SampleShadowDetailsAtPosition(Vector3 worldPosition, Camera camera = null)
Full cloud shadow breakdown at a world position. See CloudShadowSample.
void SampleShadowAtPosition(Vector3[] positions, float[] results, int count, Camera camera = null)
Fills results with the shadow amount at each position. Both arrays belong to the caller, so this overload does not allocate.
CloudShadowQuery BeginQuery(Camera camera = null)
Snapshots the current cloud state once and returns a query that can be sampled many times. Use it when sampling more than a few positions in the same frame.
CloudShadowsProfile
ScriptableObject that holds all cloud and shadow visual settings. Create via Create > Cloud Shadows Profile. Multiple components can share the same profile.
Clouds
bool showClouds
Enables rendering of volumetric clouds in the sky.
float coverage
Cloud coverage amount. Higher values produce more clouds.
float cloudsOpacity
Opacity of the rendered clouds.
float cloudsThickness
Thickness of the cloud layer, affecting visual density and lighting.
float distanceFade
Distance at which clouds fade out from the camera. Default 2500.
Color sunColor
Sun light color applied to the clouds.
Color cloudsLightColor
Color of low-density cloud areas (thinner, more transparent parts).
Color cloudsDarkColor
Color of high-density cloud areas (thicker, darker parts).
float cloudsLightIntensity
Light reflectivity intensity on clouds. Range 0–1.
float cloudsAnisotropy
Sun light intensity shining through the clouds toward the camera.
float cloudsAmbientLight
Minimum light intensity on clouds. Range 0–1.
Shadows
bool showShadows
Enables rendering of cloud shadows on the scene geometry.
float shadowCoverage
Shadow coverage amount. Can differ from cloud coverage for artistic control.
float shadowOpacity
Opacity of the cloud shadows.
Color shadowTintColor
Tint color for the cloud shadows.
bool topDownOnly
When enabled, shadows render only on top-facing surfaces (skips ceiling checks for performance).
float normalBias
Affects shadow intensity on walls and ceilings. Range -0.5 to 0.5.
float shadowMinAltitude
Prevents cloud shadows below this altitude. Useful to avoid shadows under water or terrain. Default -10000.
float preserveDirectionalShadows
Reduces cloud shadow intensity where directional light shadows exist. Range 0–1. URP only.
General
float altitude
Altitude of the cloud layer in world units.
float scale
Scale of the cloud pattern. Smaller values produce larger cloud features.
Vector3 windSpeed
Wind direction and speed for cloud animation.
Vector2 offset
UV offset for the cloud pattern.
float contrast
Contrast of the cloud pattern edges.
float edgeNoise
Amount of noise applied to cloud edges for a more natural look.
float edgeAnimationSpeed
Speed of the edge noise animation.
float noiseMultiplier
Noise intensity multiplier.
Events
event OnSettingsChanged onSettingsChanged()
Fired when profile settings are validated or changed. Subscribe to react to profile modifications.
cs.profile.onSettingsChanged += () => {
Debug.Log("Cloud settings changed");
};
CloudShadowSample
Struct returned by SampleShadowDetailsAtPosition with the intermediate values of the shadow calculation.
float haze
Cloud density at the position projected onto the cloud plane, before lighting and opacity are applied.
float shadow
Shadow factor after sun angle, normal bias, distance fade and coverage mask. Range 0–1.
float opacity
Shadow factor multiplied by the profile shadow opacity.
float darkness
Perceived darkening, from 0 (fully lit) to 1 (fully darkened). This is the value returned by SampleShadowAtPosition.
Vector3 colorMultiplier
RGB multiplier applied at that position, including the shadow tint color.
CloudShadowQuery
Read-only snapshot of the cloud state returned by BeginQuery(). Sampling through a query skips the per-call setup, so it is the cheapest way to test many positions in the same frame. Do not keep it across frames: it holds the wind and animation state of the frame it was created in.
bool isValid
False when shadows are disabled, the component is inactive or the cloud textures are not ready yet. An invalid query always reports a fully lit position.
float SampleShadowAtPosition(Vector3 worldPosition)
Shadow amount at a world position, assuming an upward facing surface.
float SampleShadowAtPosition(Vector3 worldPosition, Vector3 worldNormal)
Shadow amount at a world position on a surface with the given normal. Walls and slopes are affected by the normal bias setting.
CloudShadowSample SampleShadowDetailsAtPosition(Vector3 worldPosition)
Full shadow breakdown at a world position.
CloudShadowSample SampleShadowDetailsAtPosition(Vector3 worldPosition, Vector3 worldNormal)
Full shadow breakdown at a world position on a surface with the given normal.
void SampleShadowAtPosition(Vector3[] positions, float[] results, int count)
Batch version. The arrays belong to the caller and nothing is allocated.
void SampleShadowAtPosition(Vector3[] positions, Vector3[] normals, float[] results, int count)
Batch version with a surface normal per position.
void SampleShadowDetailsAtPosition(Vector3[] positions, CloudShadowSample[] results, int count)
Batch version returning the full breakdown for each position.
Code Examples
Basic Runtime Control
using UnityEngine;
using SSCS;
public class CloudController : MonoBehaviour {
public CloudShadows cloudShadows;
void Start() {
cloudShadows.profile.coverage = 0.6f;
cloudShadows.profile.shadowOpacity = 0.5f;
cloudShadows.profile.windSpeed = new Vector3(0.2f, 0f, 0.1f);
cloudShadows.UpdateMaterialProperties();
}
}
Day/Night Cloud Cycle
using UnityEngine;
using SSCS;
public class CloudCycle : MonoBehaviour {
public CloudShadows cloudShadows;
void Update() {
float t = Mathf.PingPong(Time.time * 0.1f, 1f);
cloudShadows.profile.coverage = Mathf.Lerp(0.2f, 0.7f, t);
cloudShadows.profile.shadowOpacity = Mathf.Lerp(0.3f, 0.8f, t);
cloudShadows.profile.cloudsOpacity = Mathf.Lerp(0.5f, 1f, t);
cloudShadows.UpdateMaterialProperties();
}
}
Limit Shadows to Play Area
using UnityEngine;
using SSCS;
public class BoundedShadows : MonoBehaviour {
public CloudShadows cloudShadows;
public Transform player;
public float areaSize = 500f;
void Start() {
cloudShadows.SetBounds(new Bounds(
player.position,
new Vector3(areaSize, 10f, areaSize)
));
cloudShadows.boundsAnchor = player;
}
}
Coverage Mask — Clear Area
using UnityEngine;
using SSCS;
public class ShadowMasking : MonoBehaviour {
public CloudShadows cloudShadows;
public GameObject building;
void Start() {
cloudShadows.coverageMask = true;
cloudShadows.MaskFillArea(building, 0, 1f, 5f);
}
}
Is the Player Under a Cloud Shadow?
using UnityEngine;
using SSCS;
public class StealthVisibility : MonoBehaviour {
public CloudShadows cloudShadows;
public Transform player;
public bool hidden;
void Update() {
float darkness = cloudShadows.SampleShadowAtPosition(player.position);
// Two thresholds instead of one, so the state does not flicker at the shadow edge
hidden = hidden ? darkness > 0.5f : darkness > 0.65f;
}
}
Sampling Many Positions at Once
using UnityEngine;
using SSCS;
public class CloudCoverGrid : MonoBehaviour {
public CloudShadows cloudShadows;
Vector3[] positions = new Vector3[256];
float[] darkness = new float[256];
void Update() {
CloudShadowQuery query = cloudShadows.BeginQuery();
if (!query.isValid) return;
query.SampleShadowAtPosition(positions, darkness, positions.Length);
}
}Suggest an improvement
Help us improve this documentation page.