Game.Simulation.GroundWaterSystem
Assembly: Assembly-CSharp.dll
Namespace: Game.Simulation
Type: class
Base: CellMapSystem
Summary:
GroundWaterSystem manages a 2D groundwater cell map used by the simulation. It stores groundwater amount, pollution and capacity per cell (via the GroundWater struct in the map), simulates pollution diffusion and water flow between neighbouring cells every tick using a Burst-compiled job (GroundWaterTickJob), and applies global replenish / purification parameters from a WaterPipeParameterData singleton. The map size is fixed to kTextureSize (256), making the groundwater grid 256x256. The system exposes helpers to sample groundwater at arbitrary world positions, consume groundwater (splitting consumption between the four surrounding cells), and to set sensible defaults (Perlin-noise-based) for new games prior to a given serialization version. The system schedules its job with Unity.Jobs and uses NativeArray
Fields
-
public const int kMaxGroundWater
Description: Maximum possible groundwater value constant (10000). Used as an upper bound for cell groundwater. -
public const int kMinGroundWaterThreshold
Description: Minimum threshold constant (500). Used by systems that need a quick threshold check for groundwater. -
public static readonly int kTextureSize
Description: Size of the groundwater texture / grid in each dimension (256). The map is kTextureSize x kTextureSize. -
private EntityQuery m_ParameterQuery
Description: Query used to fetch the WaterPipeParameterData singleton that supplies parameters used by the tick job (replenish and purification rates).
Properties
- (No public properties declared)
Although the system overrides update-interval behavior via methods (GetUpdateInterval/GetUpdateOffset), it does not expose public properties of its own. The relevant state (groundwater map) is stored in the inherited m_Map (NativeArray) from CellMapSystem .
Constructors
public GroundWaterSystem()
Description: Default constructor. Marked with [Preserve] in the class as part of the system lifecycle; initialization of textures and parameter query is done in OnCreate rather than the constructor.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Description: Returns the update interval used by the system. This system uses an interval of 128 (ticks). -
public override int GetUpdateOffset(SystemUpdatePhase phase)
Description: Returns the update offset used by the system. This system uses an offset of 64. -
public static float3 GetCellCenter(int index)
Description: Returns the world-space center of the given cell index using the CellMapSystem helper and the system's kTextureSize. -
public static bool TryGetCell(float3 position, out int2 cell)
Description: Converts a world position to a groundwater cell index (int2). Returns true if the cell is valid (within 0..kTextureSize-1 in both dimensions). -
public static bool IsValidCell(int2 cell)
Description: Returns whether a given int2 cell coordinate lies inside the 0..kTextureSize-1 grid. -
public static GroundWater GetGroundWater(float3 position, NativeArray<GroundWater> groundWaterMap)
Description: Samples groundwater at an arbitrary world position using bilinear interpolation of the four surrounding cells. Returns a GroundWater struct with interpolated m_Amount, m_Polluted and m_Max (rounded). -
public static void ConsumeGroundWater(float3 position, NativeArray<GroundWater> groundWaterMap, int amount)
Description: Attempts to consume (remove) groundwater from the four surrounding cells around the provided position. The method: - Asserts amount >= 0.
- Computes bilinear weights and the available amounts from the four surrounding cells.
- Logs a warning if trying to consume more than available.
- Distributes the consumption fractionally to each cell and updates the NativeArray accordingly.
- Uses internal helper ConsumeFraction to split consumption proportionally and consume via GroundWater.Consume.
-
Includes assertions to catch unexpected numerical edge cases.
-
private static GroundWater GetGroundWater(NativeArray<GroundWater> groundWaterMap, int2 cell)
Description: Indexed getter that returns the GroundWater value at a given cell, or default(GroundWater) if the cell is invalid. -
private static void SetGroundWater(NativeArray<GroundWater> groundWaterMap, int2 cell, GroundWater gw)
Description: Writes a GroundWater value into the map at the specified cell if the cell is valid. -
private static float Bilinear(short v00, short v10, short v01, short v11, float sx, float sy)
Description: Performs bilinear interpolation between four short values and returns a float. Used when sampling amounts/pollution/max from neighbouring cells. -
[Preserve] protected override void OnCreate()
Description: Called on system creation. Calls base.OnCreate(), creates the groundwater textures (CreateTextures(kTextureSize)) and sets up m_ParameterQuery to read the WaterPipeParameterData singleton. -
[Preserve] protected override void OnUpdate()
Description: Main update: prepares and schedules the Burst ground-water tick job (GroundWaterTickJob). The job is provided with the native groundwater map and the WaterPipeParameterData singleton. The method combines the system's read/write dependencies and registers the writer dependency (AddWriter) so other systems know when the map will be mutated. -
public override JobHandle SetDefaults(Context context)
Description: Sets default map values for new games. If context.purpose == Purpose.NewGame and context.version < Version.timoSerializationFlow, fills m_Map using 2D Perlin noise scaled to up to 10000 and assigns both m_Amount and m_Max to the same Perlin-derived value for each cell. Otherwise delegates to base.SetDefaults(context). Returns a JobHandle (usually default for this synchronous initialization).
Nested (Burst) job:
[BurstCompile] private struct GroundWaterTickJob : IJob
Description: The worker job that runs on the groundwater NativeArray each tick. The job is Burst-compiled, operates entirely on NativeArrayand a WaterPipeParameterData instance, and does the following: - Creates a temporary NativeArray
(tmp) to accumulate deltas per cell: tmp.x = amount delta, tmp.y = pollution delta. - First pass: loop through every cell and call HandlePollution on right and below neighbours to compute pollution redistribution only.
- Second pass: loop again to call HandleFlow on right and below neighbours to compute amount flow and associated pollution transfer.
-
Third pass: apply tmp deltas to each GroundWater entry, also apply global replenishment (m_GroundwaterReplenish * m_Max, CeilToInt) and subtract the m_GroundwaterPurification rate for pollution. Clamp/clamp/Math.Min/Math.Clamp calls ensure values stay within valid bounds. Finally writes back m_GroundWaterMap and disposes tmp.
-
private void HandlePollution(int index, int otherIndex, NativeArray<int2> tmp)
Purpose: Redistributes pollution between two neighbouring cells without moving the water amount; computes integer pollution shifts constrained by available clean water. -
private void HandleFlow(int index, int otherIndex, NativeArray<int2> tmp)
Purpose: Moves water amount between cells (integer amount) based on how far they are from their max, and adjusts pollution proportionally to the moved water. Uses clamps and asserts to maintain invariants. -
public void Execute()
The entry-point that orchestrates the passes and application of deltas (described above).
Notes and invariants: - The job uses assertions (Unity.Assertions) heavily to validate internal invariants during development; these may be compiled out depending on build settings. - The job uses math.clamp / Mathf.* and integer conversions; small rounding differences can matter when consuming or redistributing small amounts.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Create the underlying textures / map with the expected grid size
CreateTextures(GroundWaterSystem.kTextureSize);
// Query the WaterPipeParameterData singleton used by the tick job:
m_ParameterQuery = GetEntityQuery(ComponentType.ReadOnly<WaterPipeParameterData>());
}
[Preserve]
protected override void OnUpdate()
{
// Example of how the job is created and scheduled (actual code is in the system)
GroundWaterSystem.GroundWaterTickJob jobData = new GroundWaterSystem.GroundWaterTickJob
{
m_GroundWaterMap = m_Map,
m_Parameters = m_ParameterQuery.GetSingleton<WaterPipeParameterData>()
};
base.Dependency = Unity.Jobs.IJobExtensions.Schedule(jobData, JobHandle.CombineDependencies(m_WriteDependencies, m_ReadDependencies, base.Dependency));
AddWriter(base.Dependency);
base.Dependency = JobHandle.CombineDependencies(m_ReadDependencies, m_WriteDependencies, base.Dependency);
}
Notes for modders: - Use TryGetCell / GetCellCenter to translate world positions to map cells. - Use GetGroundWater(position, m_Map) to sample interpolated groundwater at a location. - Use ConsumeGroundWater(position, m_Map, amount) to remove groundwater for a consumer (building/service); the method splits consumption across the four surrounding cells proportionally to their available water. - If you need to modify the map directly, do so respecting the system's job dependencies (use AddWriter/reader semantics or schedule jobs that depend on the system's dependency).