Game.NetPollutionSystem
Assembly:
Game (simulation/modding assembly for Cities: Skylines 2)
Namespace:
Game.Simulation
Type:
class NetPollutionSystem
Base:
GameSystemBase
Summary:
NetPollutionSystem is an ECS system responsible for converting accumulated network (road/rail/etc.) pollution into entries on the global air and noise pollution maps. It runs in update slices (kUpdatesPerDay = 128) and schedules a Burst-compiled IJobChunk (UpdateNetPollutionJob) to process net entities (nodes and edges/curves), applying air and noise pollution to the cell maps exposed by AirPollutionSystem and NoisePollutionSystem. The job reads various component types (Node, Curve, Upgraded, Elevation, Composition, PrefabRef, connected edges) and uses prefab pollution data (NetPollutionData / NetCompositionData) together with PollutionParameterData to scale and distribute pollution into texture maps. The system also coordinates read/write dependencies with the air/noise systems.
Fields
-
public static readonly int kUpdatesPerDay = 128
{{ The number of updates that split a full "day" for network pollution processing. The system uses this constant to determine which subset of net entities to process each simulation frame. }} -
private SimulationSystem m_SimulationSystem
{{ Cached reference to the SimulationSystem (used to compute the update frame index and other time-related utilities). }} -
private EntityQuery m_PollutionQuery
{{ EntityQuery matching entities with Game.Net.Pollution and UpdateFrame components (and excluding Deleted/Temp). This query is filtered each update to only process the current update-slice of net entities. }} -
private AirPollutionSystem m_AirPollutionSystem
{{ Cached reference to the AirPollutionSystem used to get and write to the air pollution map (and to register writer job handles). }} -
private NoisePollutionSystem m_NoisePollutionSystem
{{ Cached reference to the NoisePollutionSystem used to get and write to the noise pollution map (and to register writer job handles). }} -
private EntityQuery m_PollutionParameterQuery
{{ Query used to fetch the singleton PollutionParameterData (global multipliers and radius values). Required for system execution. }} -
private TypeHandle __TypeHandle
{{ Internal helper struct storing component type/buffer/lookup handles used to build the IJobChunk (see nested TypeHandle struct). It is initialized in compiler-time helper OnCreateForCompiler. }} -
private struct UpdateNetPollutionJob
(nested)
{{ Burst-compiled IJobChunk that implements the pollution accumulation-to-map logic. It: - Reads Node/Curve/Composition/Upgraded/Elevation/PrefabRef and a ConnectedEdge buffer.
- Reads component lookups for Edge, Upgraded, Composition, NetPollutionData, NetCompositionData.
- Has NativeArrays for the air/noise maps and parameters for map size and texture sizes.
- For each chunk: lerps accumulated pollution toward the instant pollution, clears per-frame pollution, inspects connected edges (for nodes) or curve data (for edges), adjusts noise pollution for upgrades and beautification/sound barriers, and calls internal helper methods to write to the maps (AddAirPollution, AddNoise, AddNoiseSingle).
-
Splits noise addition across multiple sample points for wide networks and distributes contributions bilinearly when mapping to the noise texture cells. This job is scheduled in OnUpdate and its job handle is registered with the air/noise systems so they are aware of writers. }}
-
private struct TypeHandle
(nested)
{{ Holds ComponentTypeHandle, BufferTypeHandle and ComponentLookup fields used to obtain fast accessors for the UpdateNetPollutionJob. The __AssignHandles method binds these handles to a SystemState (called during setup / OnCreateForCompiler). This pattern is typical for generated ECS code to avoid repeated handle creation at runtime. }}
Properties
- (none public)
{{ NetPollutionSystem itself exposes no public properties. It operates via ECS queries and internal state. The nested job struct contains public job fields used to pass data into the job when scheduled. }}
Constructors
public NetPollutionSystem()
{{ Default constructor (preserved). The ECS framework will construct the system; most initialization is performed in OnCreate. }}
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
{{ Returns the system's update interval relative to the given phase. The implementation returns a value derived from kUpdatesPerDay (262144 / (kUpdatesPerDay * 16)), controlling how often the system's update logic runs in the overall simulation phases. Use this to tune how frequently the system wakes relative to other simulation systems. }} -
protected override void OnCreate()
{{ System setup: fetches/caches required systems (SimulationSystem, AirPollutionSystem, NoisePollutionSystem), builds the m_PollutionQuery (Game.Net.Pollution + UpdateFrame, excluding Deleted/Temp), and m_PollutionParameterQuery for PollutionParameterData. Calls RequireForUpdate on both queries so the system runs only when relevant data exists. This is where the system prepares to run its chunk job. }} -
protected override void OnUpdate()
{{ Core runtime behavior: - Compute the updateFrame using SimulationUtils.GetUpdateFrame with m_SimulationSystem.frameIndex and kUpdatesPerDay.
- Filter m_PollutionQuery to entities matching the computed UpdateFrame.
- Prepare and schedule the Burst-compiled UpdateNetPollutionJob, passing in component type/lookup handles, the air/noise maps (obtained from their systems) and pollution parameters.
- Combine dependencies from obtaining the maps and schedule the job with the query.
- Register the returned job handle as a writer with both AirPollutionSystem and NoisePollutionSystem so they know about the pending writes.
-
Store the scheduled job handle into the system's base.Dependency. This method coordinates access to the global pollution maps and ensures the job runs safely with the ECS job system. }}
-
protected override void OnCreateForCompiler()
{{ Internal helper called by generated/compiled code to assign queries and type handles so the job code has correct handles tied to the SystemState. This is necessary for ECS code generation patterns and ensures __AssignQueries and __TypeHandle.__AssignHandles are invoked. }} -
private void __AssignQueries(ref SystemState state)
{{ Compiler helper that (in this code) simply constructs an EntityQueryBuilder to ensure query initialization for the compiler. In generated patterns this method can bind additional queries; here it is a placeholder used during code-gen/compilation. }} -
Nested job helpers inside UpdateNetPollutionJob:
-
Execute(in ArchetypeChunk chunk, ...)
{{ Processes a chunk of entities (either nodes or curves) and applies accumulation/clear/update logic. Handles:- Lerp accumulation with pollution over time,
- Retrieve NetPollutionData and NetCompositionData from prefab lookups,
- For node entities: iterate connected edges, inspect composition/upgrades, compute noise/air factors and call ApplyPollution for point-like sources.
- For curve/edge entities: sample along the curve length, split air contributions across samples, and distribute noise along the curve with tangent-based offsets. The job writes into the provided native arrays for air/noise maps. }}
-
CheckUpgrades(ref float3 noisePollution, Upgraded upgraded)
{{ Examines the Upgraded flags for left/right side sound barriers and beautification features and modifies noisePollution components accordingly. Sound barrier flags cut certain directions' noise; beautification reduces noise and balances components. }} -
ApplyPollution(float3 position, float radius, float2 noisePollution, float airPollution, ref PollutionParameterData pollutionParameters)
{{ Applies pollution for a point-like network position (usually a node). Uses PollutionParameterData multipliers. Adds air pollution to the air map (AddAirPollution) and distributes noise in a cross pattern or four-corner pattern on the noise map depending on radius. }} -
ApplyPollution(Curve curve, float radius, float3 noisePollution, float airPollution, ref PollutionParameterData pollutionParameters)
{{ Applies pollution along a curve (edge). Splits air pollution into multiple samples along the curve and distributes noise similarly but with orientations computed from the curve tangent (uses MathUtils.Position/MathUtils.Tangent). The number of samples is computed based on texture/map resolution to keep sampling density stable. }} -
AddAirPollution(float3 position, short amount)
{{ Converts world position to an AirPollution cell (CellMapSystem.GetCell) and writes the provided short amount into the air pollution map at that cell via a read-modify-write operation on the NativeArray . }} -
AddNoise(float3 position, short amount)
{{ Maps a world position to fractional cell coords on the noise map, computes bilinear weights for the four surrounding cells, and dispatches those weighted amounts to AddNoiseSingle. This ensures noise contributions are smoothly distributed across the discrete noise texture. }} -
AddNoiseSingle(int2 cell, short amount)
{{ Bounds-checks the cell and, if valid, adds the short amount to the corresponding cell in the noise pollutions native array. }}
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Example of what the real system does: cache systems and build queries.
m_SimulationSystem = base.World.GetOrCreateSystemManaged<SimulationSystem>();
m_AirPollutionSystem = base.World.GetOrCreateSystemManaged<AirPollutionSystem>();
m_NoisePollutionSystem = base.World.GetOrCreateSystemManaged<NoisePollutionSystem>();
m_PollutionQuery = GetEntityQuery(
ComponentType.ReadWrite<Game.Net.Pollution>(),
ComponentType.ReadOnly<UpdateFrame>(),
ComponentType.Exclude<Deleted>(),
ComponentType.Exclude<Temp>());
m_PollutionParameterQuery = GetEntityQuery(ComponentType.ReadOnly<PollutionParameterData>());
RequireForUpdate(m_PollutionQuery);
RequireForUpdate(m_PollutionParameterQuery);
}
Notes and tips for modders: - The system relies on prefab NetPollutionData and NetCompositionData to determine how much pollution each network prefab produces and how it's distributed. Changing those prefab data values (via mod or content override) will affect noise/air outputs. - Upgrades and CompositionFlags (sound barriers, beautification) are interpreted in CheckUpgrades to attenuate or redistribute noise — mods that add or modify Upgrade flags should align with these behavior expectations. - Air pollution is sampled at a lower resolution (AirPollutionSystem.kTextureSize) and is accumulated in short-valued cells. Noise pollution uses bilinear distribution based on fractional cell coordinates to avoid aliasing. - When debugging, inspect the scheduled job dependencies and ensure other systems that read the pollution maps respect the writer registration (AddWriter) to avoid race conditions.