Game.Simulation.AirPollutionSystem
Assembly: Game
Namespace: Game.Simulation
Type: class
Base: CellMapSystem
Summary:
AirPollutionSystem manages the game's 2D air pollution cell map (256x256). It advects pollution using wind, applies diffusion/spread and fade each simulation update, and stores pollution values in a CellMap texture-backed array. The system schedules a Burst-compiled job (AirPollutionMoveJob) that reads wind data from WindSystem and pollution parameters from a PollutionParameterData singleton (via an entity query). Pollution advection is stochastic (uses RandomSeed) and includes bilinear sampling for queries. The system integrates with the simulation dependency model (readers/writers) and runs on a fixed update interval.
Fields
-
private static readonly int kSpread = 3
Describes how much pollution spread is applied when sampling neighbouring cells. It's used as a right-shift amount when adding neighbour contributions. -
public static readonly int kTextureSize = 256
Size of the pollution texture/map in each dimension (256x256). -
public static readonly int kUpdatesPerDay = 128
Number of pollution updates per in-game day. Used to derive fade rate and the update interval. -
private WindSystem m_WindSystem
Cached reference to the WindSystem (used to get wind map and drive advection). -
private SimulationSystem m_SimulationSystem
Cached reference to the SimulationSystem (used to read the current frame index). -
private EntityQuery m_PollutionParameterQuery
EntityQuery used to obtain PollutionParameterData singleton (contains m_WindAdvectionSpeed, m_AirFade, etc.).
Properties
public int2 TextureSize { get; }
Returns the texture/map dimensions as an int2: (kTextureSize, kTextureSize). Use this to know the cell-map resolution (256x256).
Constructors
public AirPollutionSystem()
Default constructor. No special initialization beyond base constructor. The real initialization happens in OnCreate.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns the update interval (in simulation ticks) for the system: 262144 / kUpdatesPerDay. With kUpdatesPerDay = 128 this evaluates to 2048 ticks. This controls how often the system's OnUpdate runs relative to the simulation phase. -
public static float3 GetCellCenter(int index)
Get the world-space center position of the given pollution cell index. Delegates to CellMapSystem.GetCellCenter with kTextureSize. -
public static AirPollution GetPollution(float3 position, NativeArray<AirPollution> pollutionMap)
Sample pollution at an arbitrary world position. Performs bilinear interpolation between the four surrounding pollution cells. Steps: - Converts position to cell coordinates in the 256x256 map.
- Clamps cell indices to valid range (0..kTextureSize-2) so the 2x2 sample is valid.
-
Reads four neighbouring short pollution values from the provided NativeArray and returns an AirPollution with the bilinearly-interpolated short value (rounded).
-
[Preserve] protected override void OnCreate()
Initializes the system: - Calls base.OnCreate().
- Calls CreateTextures(kTextureSize) to allocate the map texture/array.
- Caches references to WindSystem and SimulationSystem from the world (GetOrCreateSystemManaged).
-
Builds an EntityQuery for PollutionParameterData and calls RequireForUpdate so the system only runs when parameters exist.
-
[Preserve] protected override void OnUpdate()
Prepares and schedules the AirPollutionMoveJob: - Retrieves the wind map from WindSystem via GetMap(readOnly: true, out dependencies).
- Reads the PollutionParameterData singleton from m_PollutionParameterQuery.
- Creates a job struct (AirPollutionMoveJob) with m_PollutionMap = m_Map (the CellMap backing array), the wind map, pollution parameters, a RandomSeed, and current frame index.
- Schedules the job using JobUtils.CombineDependencies and IJobExtensions.Schedule; integrates the job handle with the system's m_ReadDependencies and m_WriteDependencies.
-
Registers the scheduled dependency with WindSystem.AddReader and AddWriter, then combines dependencies into base.Dependency.
-
private struct AirPollutionMoveJob : IJob
(Burst compiled)
Implements the per-update pollution advection, diffusion/spread and fade. Key behavior in Execute(): - Allocates a temporary NativeArray
same length as the pollution map to store advected values. - For each cell index:
- Computes the cell center.
- Samples wind at the cell center using WindSystem.GetWind (via provided wind map).
- Samples pollution from an upwind position: position - m_WindAdvectionSpeed * wind.xy (m_WindAdvectionSpeed comes from PollutionParameterData).
- Writes that sampled pollution into the temporary buffer.
- Applies diffusion & fade in a second pass over kTextureSize x kTextureSize:
- For each cell sums neighbour contributions (right-shifted by kSpread).
- Subtracts a portion of the cell's own pollution and a randomized fade amount (uses Random and m_PollutionParameters.m_AirFade / kUpdatesPerDay).
- Clamps the result to 0..32767 and writes back into the main m_PollutionMap.
- Disposes the temporary array.
Notes on threading and safety: - The job is Burst compiled and uses NativeArray for parallel safety. - Reads the wind map as ReadOnly. - The job uses RandomSeed to create per-frame Random for stochastic rounding in fading.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Allocate the map/texture used to store pollution
CreateTextures(AirPollutionSystem.kTextureSize);
// Cache systems we depend on
m_WindSystem = World.GetOrCreateSystemManaged<WindSystem>();
m_SimulationSystem = World.GetOrCreateSystemManaged<SimulationSystem>();
// Only run when PollutionParameterData exists
m_PollutionParameterQuery = GetEntityQuery(ComponentType.ReadOnly<PollutionParameterData>());
RequireForUpdate(m_PollutionParameterQuery);
}
Additional notes / tips: - To query pollution at a world position from outside the system, obtain the map array (if exposed) or add a public helper that calls AirPollutionSystem.GetPollution(position, pollutionMap). GetPollution expects the NativeArray backing the map, and performs bilinear interpolation. - The advection uses PollutionParameterData.m_WindAdvectionSpeed to displace the sample point in the opposite direction of the wind, so tuning those parameters (and m_AirFade) adjusts how pollution moves and dissipates. - The job uses bit-shifts (kSpread) to approximate diffusion/spread cheaply; changing kSpread alters diffusion strength.