Game.ClimateRenderSystem
Assembly: Assembly-CSharp (typical for game code; replace with actual assembly if different)
Namespace: Game.Rendering
Type: class
Base: GameSystemBase
Summary:
ClimateRenderSystem is a rendering-level system responsible for driving visual climate effects in Cities: Skylines 2. It coordinates volumetric clouds, precipitation VFX (rain, snow, hail), lightning VFX, wind textures, and a small climate-control Volume that exposes weather-related overrides. The system bridges simulation state (ClimateSystem, SimulationSystem, TimeSystem) with rendering and audio subsystems to produce synchronized weather visuals and sound. It also exposes a small API for scheduling weather prefab transitions and queuing/dispatching lightning strikes for use by other systems or jobs.
Fields
-
private static class VFXIDs
Static container of Shader.PropertyToID integer IDs used by the precipitation/lightning VFX (CameraPosition, CameraDirection, VolumeScale, WindTexture, CloudsAltitude, MapOffsetScale, RainStrength, SnowStrength, LightningOrigin, LightningTarget). Used to set VFX parameters efficiently. -
private enum PrecipitationType
Local enum listing precipitation kinds (Rain, Snow, Hail) used to translate system state to VFX events/names. -
[StructLayout(LayoutKind.Sequential, Size = 1)] private struct TypeHandle
Compiler-generated small struct used to assign Entity query handles. Internal plumbing for DOTS/ECS integration. -
private RenderingSystem m_RenderingSystem
Reference to the rendering system used to obtain frame timing and camera frame data. -
private ClimateSystem m_ClimateSystem
Reference to the simulation climate system (source of precipitation, temperature, hail, etc.). -
private SimulationSystem m_SimulationSystem
Reference to the simulation system (used to pause or read sim speed when necessary). -
private CameraUpdateSystem m_CameraUpdateSystem
Reference to camera data (position, direction) used to drive VFX uniforms and volumetric cloud behaviour. -
private PrefabSystem m_PrefabSystem
Used to resolve prefabs referenced by event entities. -
private WindTextureSystem m_WindTextureSystem
Provides the wind texture used by precipitation VFX. -
private TerrainSystem m_TerrainSystem
Provides map offset/scale used by VFX (MapOffsetScale). -
private TimeSystem m_TimeSystem
Used to compute time-of-year for climate sampling. -
private AudioManager m_AudioManager
Used to play lightning SFX. -
public bool globalEffectTimeStepFromSimulation
If true, VFX fixed timestep is controlled by simulation time step & simulation speed (applies to VFXManager.fixedTimeStep). -
public bool weatherEffectTimeStepFromSimulation = true
If true, precipitation/lightning VisualEffect play rate is scaled according to simulation timestep; otherwise uses 1. -
private static VisualEffectAsset s_PrecipitationVFXAsset
Static cached VisualEffectAsset loaded from Resources ("Precipitation/PrecipitationVFX"). -
private VisualEffect m_PrecipitationVFX
Instanced VisualEffect used to drive precipitation VFX (created at runtime on demand). -
private static VisualEffectAsset s_LightningVFXAsset
Static cached VisualEffectAsset loaded from Resources ("Lightning/LightningBolt"). -
private VisualEffect m_LightningVFX
Instanced VisualEffect used to drive lightning VFX. -
private Volume m_ClimateControlVolume
A post-processing/volume object created to host WeatherPropertiesStack components (volumetric clouds, wind, etc). -
private VolumetricClouds m_VolumetricClouds
Volume component referencing volumetric cloud settings used and updated by the system. -
private WindVolumeComponent m_Wind
Volume component referencing wind configuration. -
private WindControl m_WindControl
Instance wrapper providing additional wind control / lifetime handling. -
private bool m_IsRaining
Internal flag tracking if rain VFX is currently active. -
private bool m_IsSnowing
Internal flag tracking if snow VFX is currently active. -
private bool m_HailStorm
Internal flag tracking if hail VFX is currently active. -
private EntityQuery m_EventQuery
EntityQuery used to scan for WeatherPhenomenon event entities so the system can instantiate/display associated prefabs as needed. -
private NativeQueue<LightningStrike> m_LightningStrikeQueue
Thread-safe queue used by jobs / other systems to enqueue lightning strike requests processed on the main/render thread. -
private JobHandle m_LightningStrikeDeps
JobHandle representing dependencies for writers that enqueue lightning strikes (to ensure their producers complete before consumption). -
private WeatherPropertiesStack m_PropertiesStack
Container that manages weather override properties stored in the climate control volume; used to interpolate and apply overrideable properties. -
private readonly List<WeatherPrefab> m_FromWeatherPrefabs = new List<WeatherPrefab>()
List of weather prefabs representing the current "from" state when interpolating between weather configurations. -
private readonly List<WeatherPrefab> m_ToWeatherPrefabs = new List<WeatherPrefab>()
List of weather prefabs representing the target "to" state when interpolating. -
private bool m_PropertiesChanged
Flag indicating that scheduled from/to prefab lists changed and SetData should be called before the next interpolation. -
private TypeHandle __TypeHandle
Compiler-generated handle used internally to map component types to query handles. -
private EntityQuery __query_100321765_0
Compiler-generated EntityQuery used for TimeSettingsData. -
private EntityQuery __query_100321765_1
Compiler-generated EntityQuery used for TimeData.
Properties
-
public float precipitationVolumeScale { get; set; } = 30f
Controls the cubic scale of the precipitation VFX volume in world units. Default is 30. Modding tip: increasing this expands the effective VFX volume (affects particle spawning bounds); decreasing shrinks it. -
public bool editMode { get; set; }
When true, interpolation and property application may behave in an editor-friendly way (used by the system to alter behavior in UI/edit contexts). -
public bool pauseSimulationOnLightning { get; set; }
When true, triggering LightningStrike will set simulation speed to 0 (pauses simulation) — used to emphasize lightning events. -
internal WeatherPropertiesStack propertiesStack => m_PropertiesStack
Internal access to the WeatherPropertiesStack for interrogating or modifying applied overrides. -
public IReadOnlyList<WeatherPrefab> fromWeatherPrefabs => m_FromWeatherPrefabs
Read-only view of the scheduled "from" weather prefabs. -
public IReadOnlyList<WeatherPrefab> toWeatherPrefabs => m_ToWeatherPrefabs
Read-only view of the scheduled "to" weather prefabs. -
public bool IsAsync { get; set; }
Flag indicating whether the system is operating asynchronously (affects some timing choices).
Constructors
public ClimateRenderSystem()
Default constructor. Most initialization occurs in OnCreate (DOTS-style). No parameters; system is created by the world.
Methods
-
private void SetData(WeatherPropertiesStack stack, IReadOnlyList<WeatherPrefab> fromPrefab, IReadOnlyList<WeatherPrefab> toPrefab)
Collects overrideable properties from the provided weather prefabs and configures the WeatherPropertiesStack appropriately. Distinguishes between immediate overrides and time-based interpolation overrides. -
public void Clear()
Clears scheduled from/to weather prefab lists and marks properties changed so SetData is re-run on next update. -
public void ScheduleFrom(WeatherPrefab prefab)
Append a WeatherPrefab to the "from" list for interpolation/transition setup. -
public void ScheduleTo(WeatherPrefab prefab)
Append a WeatherPrefab to the "to" list for interpolation/transition setup. -
private float GetTimeOfYear()
Returns normalized time-of-year used to sample ClimateSystem. If ClimateSystem has an override date it uses that; otherwise it queries TimeSettingsData and TimeData singletons and computes rendering-frame-aligned time-of-year. If absent, returns 0.5. -
private void UpdateWeather()
Samples ClimateSystem using time-of-year, ensures SetData has been applied when scheduled lists changed, and advances interpolation in WeatherPropertiesStack using both simulation and rendering time information. Also respects editMode. -
private void UpdateEffectsState()
Decides which precipitation VFX events (rain/snow/hail start/stop) should be fired based on m_ClimateSystem.precipitation, hail, and temperature. Maintains m_IsRaining/m_IsSnowing/m_HailStorm internal state. -
[Preserve] protected override void OnCreate()
Initializes references to subsystems (ClimateSystem, RenderingSystem, SimulationSystem, CameraUpdateSystem, PrefabSystem, WindTextureSystem, TerrainSystem, TimeSystem, AudioManager), creates the climate-control Volume and WeatherPropertiesStack, obtains/creates VolumetricClouds and Wind volume components, sets up resources and queries, and allocates the lightning queue. Also loads VisualEffectAssets from Resources ("Precipitation/PrecipitationVFX", "Lightning/LightningBolt"). -
private void ResetOverrides()
Resets volumetric cloud volume overrides to disabled/defaults (helper used during initialization). -
public NativeQueue<LightningStrike> GetLightningStrikeQueue(out JobHandle dependencies)
Returns the NativeQueue used for lightning strike requests and outputs the current job dependencies (so producers can add their JobHandle with AddLightningStrikeWriter). -
[Preserve] protected override void OnUpdate()
Main update: if there's an active viewer, it updates weather interpolation, volumetric clouds, ensures VFX instances exist, updates precipitation/lighting state and properties, and adjusts VFX speed/playrate. It also iterates event entities, resolves any WeatherPhenomenon prefabs, completes and consumes the lightning queue, and triggers LightningStrike for queued entries. -
public void AddLightningStrikeWriter(JobHandle jobHandle)
Registers a producer JobHandle so the system knows dependencies before consuming the m_LightningStrikeQueue. Call this from systems/jobs that enqueue lightning strikes. -
private void UpdateVolumetricClouds()
Adjusts volumetric cloud FadeIn settings and render hook depending on camera altitude/direction (makes clouds render correctly above or below camera). -
[Preserve] protected override void OnDestroy()
Completes any pending lightning job dependencies, disposes the lightning queue, disposes WindControl and WeatherPropertiesStack, destroys the climate volume, and performs base cleanup. -
private void CreateDynamicVFXIfNeeded()
Instantiates a GameObject+VisualEffect for precipitation and lightning at runtime when their VisualEffectAssets are loaded and instances are missing. Ensures a small pool (one instance each) exists. -
public void LightningStrike(float3 start, float3 target, bool useCloudsAltitude = true)
Trigger an immediate lightning event. Optionally sets start.y to sit in the cloud volume altitude. If pauseSimulationOnLightning is true, sets simulation speed to 0. Sends VFX event and plays lightning SFX. -
private bool GetEventName(PrecipitationType type, bool start, out string name)
Internal helper mapping PrecipitationType + start/stop state to VFX event name strings (e.g., "OnRainStart"/"OnRainStop"). -
private void UpdateEffectState(PrecipitationType type, bool start)
Uses GetEventName and sends the appropriate event to the precipitation VisualEffect instance to start/stop precipitation. -
private void UpdateEffectsProperties()
Syncs VFX uniforms/parameters: camera position/direction, volume scale, wind texture, cloud altitude, map offset/scale, rain/snow strengths from ClimateSystem, etc. Uses SetChecked* helpers to avoid setting null textures or absent VFX. -
private void UpdateVFXSpeed()
Adjusts VFXManager.fixedTimeStep or VisualEffect.playRate depending on globalEffectTimeStepFromSimulation and weatherEffectTimeStepFromSimulation to keep VFX time progression consistent with simulation/rendering speeds. -
[MethodImpl(MethodImplOptions.AggressiveInlining)] private void __AssignQueries(ref SystemState state)
Compiler-generated: builds internal queries for TimeSettingsData and TimeData. -
protected override void OnCreateForCompiler()
Compiler helper that calls __AssignQueries and assigns TypeHandle handles. Not normally called by mod code. -
private void __AssignHandles(ref SystemState state)
Compiler-generated small helper invoked by OnCreateForCompiler to populate handles (present on TypeHandle struct).
Usage Example
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.VFX;
// inside a system/behavior that has a reference to ClimateRenderSystem:
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Example: tweak precipitation volume and enable edit mode for editor UI previews
var climate = World.GetOrCreateSystemManaged<Game.Rendering.ClimateRenderSystem>();
climate.precipitationVolumeScale = 50f;
climate.editMode = true;
// Schedule weather prefabs (assuming you have references to WeatherPrefab instances)
// climate.ScheduleFrom(currentWeatherPrefab);
// climate.ScheduleTo(targetWeatherPrefab);
// Trigger a manual lightning strike at runtime:
float3 start = new float3(100f, 0f, 200f);
float3 target = new float3(110f, 0f, 210f);
climate.LightningStrike(start, target);
// If a job will enqueue lightning, register its JobHandle before the system consumes the queue:
// JobHandle writerJobHandle = ...;
// climate.AddLightningStrikeWriter(writerJobHandle);
}
Additional notes and modding tips: - VisualEffectAssets are loaded via Resources at paths "Precipitation/PrecipitationVFX" and "Lightning/LightningBolt". Replace or override those assets in modded Resources or intercept creation if you want custom VFX. - precipitationVolumeScale affects the VFX volume used for particle emission; adjust it to fit your city camera heights. - Use GetLightningStrikeQueue/AddLightningStrikeWriter to enqueue lightning strikes from background jobs safely. Always supply a JobHandle via AddLightningStrikeWriter so the render system completes producers before consuming the queue. - The system manages a Volume (m_ClimateControlVolume) and WeatherPropertiesStack — disposing or destroying that volume externally will break the interpolation pipeline; prefer interacting through the exposed propertiesStack when modifying overrides. - Be cautious when setting globalEffectTimeStepFromSimulation: changing VFXManager.fixedTimeStep affects all VisualEffect playback globally and may have side effects for other systems using VFXManager.