Game.SoilWaterSystem
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: class
Base: CellMapSystem
Summary:
SoilWaterSystem manages a discrete soil-water map used by the simulation to model soil moisture, interactions with surface water, rainfall, and flood events. It maintains a 128×128 RFloat texture (SoilWaterTexture) that shaders can read, updates a NativeArray-backed map of SoilWater cells on a scheduled job (SoilWaterTickJob), computes diffusion between neighboring cells, applies rainfall/overflow logic, and triggers Flood events via an Entity-based flood counter. The system interacts with TerrainSystem, WaterSystem, ClimateSystem and uses an EndFrameBarrier to emit event entities safely. Key modding touchpoints: the soil texture (Texture2D, RFloat), SoilWaterParameterData (singleton) for tuning behavior, and flood control via Flood/FloodData/FloodCounterData entities.
Fields
-
public static readonly int kTextureSize = 128
128 — width and height of the soil map / texture. Each cell in the internal map corresponds to one texel. Use this constant when indexing the texture. -
public static readonly int kUpdatesPerDay = 1024
Number of internal soil update ticks considered per day; used to compute update distribution and scheduling. -
public static readonly int kLoadDistribution = 8
Number of slices that split the map for incremental updates across frames. -
private SimulationSystem m_SimulationSystem
Reference to the SimulationSystem used to obtain frame indices and general simulation timing. -
private TerrainSystem m_TerrainSystem
Reference to the TerrainSystem — used to sample terrain heights inside the scheduled job to compute soil surface heights. -
private WaterSystem m_WaterSystem
Reference to the WaterSystem — used to obtain water surface data (depths/resolution) consumed when computing soil-water exchange and flooding. -
private ClimateSystem m_ClimateSystem
Reference to the ClimateSystem — used to read precipitation (m_Weather / rainfall intensity) that increases soil water. -
private EndFrameBarrier m_EndFrameBarrier
Barrier used to produce event entities (flood starter/stopper) safely at the end of the frame. Jobs write into an EntityCommandBuffer produced by this barrier. -
private Texture2D m_SoilWaterTexture
Managed Texture2D (RFloat) that mirrors shader-usable soil-water data. GetRawTextureData() returns the per-cell float values written by the job. Texture is created as 128×128, TextureFormat.RFloat, linear, no mip chain. -
private EntityQuery m_SoilWaterParameterQuery
Query to obtain the singleton SoilWaterParameterData that contains multiple tuning parameters (rain multiplier, maximum depth, overflow rate, diffusion parameters, etc). -
private EntityQuery m_FloodQuery
Query for active Flood entities in the world. Used to detect whether a flood is currently active. -
private EntityQuery m_FloodPrefabQuery
Query for FloodData prefabs (prefab event archetypes) used to spawn flood events when the flood counter exceeds threshold. -
private TypeHandle __TypeHandle
Generated helper struct that holds ComponentLookup handles (WaterLevelChange, FloodCounterData, EventData) used inside jobs. The handles are assigned in OnCreateForCompiler. -
private EntityQuery __query_336595330_0
Generated query used internally to obtain the FloodCounterData entity (single entity used to track a counter). PostDeserialize ensures such entity exists.
Notes for modders: - The texture is updated by the job; do not overwrite it directly without coordinating with system jobs. Read-only access to the texture's raw data is safe on the main thread after the system ensures Apply() and job completion. - To change simulation behavior, create or modify the SoilWaterParameterData singleton entity. This is the intended tuning point.
Properties
-
public int2 TextureSize => new int2(kTextureSize, kTextureSize)
Provides the texture/map size as int2 {128,128}. Useful for sampling and indexing code. -
public Texture soilTexture => m_SoilWaterTexture
Exposes the RFloat Texture2D that contains soil-water shader data. Use Texture.GetRawTextureData() to access the per-cell float values (layout: x + y * kTextureSize).
Constructors
public SoilWaterSystem()
Default constructor (generated/preserved). Initialization happens in OnCreate.
Methods
-
protected override void OnCreate()
Initializes subsystem references (SimulationSystem, TerrainSystem, WaterSystem, ClimateSystem), creates an EndFrameBarrier reference, prepares EntityQueries, creates a FloodCounter entity if needed, allocates and initializes the RFloat texture (SoilWaterTexture), and initializes the internal map (m_Map) with default SoilWater values (m_Amount = 1024, m_Max = 8192). Registers RequireForUpdate on SoilWaterParameterData so the system runs only when parameters exist. Important: the texture is created with name "SoilWaterTexture" and hideFlags = HideAndDontSave. -
protected override void OnUpdate()
Main scheduling method. If TerrainHeightData is available, it calls m_SoilWaterTexture.Apply(), reads precipitation from ClimateSystem, computes shaderUpdatesPerSoilUpdate and loadDistributionIndex, constructs a SoilWaterTickJob (populating component lookups, water surface data, flood entity lists and other inputs), schedules the job (combining dependencies and registering write/read dependencies), attaches the job to EndFrameBarrier, and sets up readers for TerrainSystem and WaterSystem. The job updates the internal map, writes per-cell shader data into the texture raw buffer, increments/decrements flood counters and starts/stops flood events. -
private void CreateFloodCounter()
Creates a new entity with FloodCounterData component. Called from OnCreate and PostDeserialize if no counter exists. -
public void PostDeserialize(Context context)
Deserialization hook — verifies a FloodCounterData entity exists after load and creates one if none present. This ensures saved game loads don't lose the flood counter. -
private void __AssignQueries(ref SystemState state)
Generated helper used in OnCreateForCompiler to build the internal entity query used to retrieve the single FloodCounterData entity. Not normally called by modders. -
protected override void OnCreateForCompiler()
Generated method invoked to assign queries and component lookups into the TypeHandle. Ensures that the compiled component lookups are available to jobs.
Inner types and jobs:
private struct SoilWaterTickJob : IJob
The job that performs the per-slice soil-water simulation. Responsibilities:- Handles diffusion between neighboring cells by calling HandleInterface (considers elevation difference and relative saturation).
- Applies rainfall (based on climate precipitation) and computes an effective rain multiplier.
- Samples water surface depths from WaterSurfaceData (depth array) to compute water-soil interactions (infiltration, overflow).
- Updates each cell's m_Amount, applies overflow logic (m_OverflowRate), and writes a per-cell shader value into the soil texture raw float array.
- Maintains and updates FloodCounterData; when counter exceeds thresholds it uses EntityCommandBuffer to Create flood event entities (StartFlood) or mark existing flood entities as Deleted (StopFlood).
- Uses ComponentLookup to read/write WaterLevelChange, FloodCounterData, and EventData. Important details:
- The job iterates only over a slice of the map determined by m_LoadDistributionIndex and kLoadDistribution (so not all cells are updated each frame).
- The texture buffer m_SoilWaterTextureData is a float[] (raw RFloat texel buffer) and receives incremental per-job contributions. Shader updates are scaled by m_ShaderUpdatesPerSoilUpdate.
-
Watch for the numeric mapping: one float per cell, order is row-major: index = x + y * kTextureSize.
-
private struct TypeHandle
Generated struct holding ComponentLookup handles for the job: WaterLevelChange (read/write), EventData (read-only), FloodCounterData (read/write). It contains __AssignHandles(ref SystemState) to initialize lookup handles.
Usage notes (modding):
- To tune the soil simulation, modify or create a SoilWaterParameterData singleton entity with your desired parameters. This is the official configuration point.
- To read the soil texture from a custom shader or manager:
- Get the system from the world: var s = World.GetExistingSystemManaged
Usage Example
// Example: read soil water float value at a cell (main thread)
var world = World.DefaultGameObjectInjectionWorld; // or appropriate world in mod context
var soilSystem = world.GetExistingSystemManaged<Game.Simulation.SoilWaterSystem>();
if (soilSystem != null)
{
Texture tex = soilSystem.soilTexture;
var raw = tex.GetRawTextureData<float>(); // one float per cell, row-major
int x = 10;
int y = 20;
int idx = x + y * Game.Simulation.SoilWaterSystem.kTextureSize;
float value = raw[idx]; // this value corresponds to shader delta/infiltration contribution
Debug.Log($"Soil texture value at ({x},{y}) = {value}");
}
// Example: change soil parameters - create/modify the singleton SoilWaterParameterData entity
var em = world.EntityManager;
if (!em.HasComponent<SoilWaterParameterData>(soilParamEntity))
{
// Create and set up a singleton SoilWaterParameterData as needed.
}
// Example: sample interpolated SoilWater m_Amount from the internal map is NOT exposed publicly.
// Use soilTexture for visual/shader-driven sampling, or create a small system that reads and exposes needed data.
Notes: - The system schedules its work in a job (SoilWaterTickJob) and writes to the texture raw buffer. Ensure you respect the system's job dependencies if you access the texture raw data outside the system — wait for the system to complete. - Altering internal data structures (m_Map) is not supported directly — use provided parameter singletons or entity components designed for the purpose.