Skip to content

Game.Simulation.WaterSystem

Assembly: Game
Namespace: Game.Simulation

Type: class

Base: GameSystemBase, IDefaultSerializable, ISerializable, IGPUSystem

Summary:
WaterSystem is the central simulation manager for surface water in the game. It manages GPU-driven water simulation (height, velocity and flow maps), water sources (rivers/sea/constant sources), readbacks for CPU-side queries, active-tile culling for performance, and interactions with terrain, snow and soil-water systems. The system schedules jobs to gather water sources, drives compute shader kernels to update water textures, handles serialization/deserialization of the water surface state, and exposes runtime APIs for querying water depth/velocity and for controlling simulation behaviour (speed, downscaling, flow blur, etc.).


Fields

  • public static readonly int kMapSize
    Constant world map size in meters used by the water system (14336). Used to translate world-space positions to water texture cells and vice versa.

  • public static readonly float kDefaultMinWaterToRestoreHeight
    Default minimum height threshold used when restoring water from heightmap (-5f).

  • private static float s_SeaLevel
    Current global sea level tracked by the water system (updated from constant-depth sources).

  • private QuadWaterBuffer m_Water
    Container holding RenderTextures used by the water simulation (water textures and downscaled flow textures). Responsible for allocation and disposal of GPU textures.

  • private ComputeBuffer m_Active
    GPU compute buffer storing active-tile flags/indices for spatial culling. Filled from CPU or via GPU readback.

  • private NativeArray<int> m_ActiveCPU
    CPU-side buffer mirroring active tiles (used to decide which areas to simulate on CPU side).

  • private SurfaceDataReader m_depthsReader
    Helper that reads depth data from the GPU water texture into CPU-accessible arrays (async readback).

  • private SurfaceDataReader m_velocitiesReader
    Helper that reads flow/velocity data from the GPU downscaled flow texture into CPU-accessible arrays.

  • private ComputeShader m_UpdateShader
    Compute shader that implements major simulation kernels (velocity update, depth update, downsample, blur, add sources, evaporate, etc.).

  • private int m_TexSize.x/y (int2 m_TexSize)
    Current water texture resolution (default 2048x2048) stored in int2.

  • private ulong m_NextSimulationFrame
    Monotonic frame counter used for scheduling readbacks and for tracking simulation time progression.

  • private CommandBuffer m_CommandBuffer
    CommandBuffer used to dispatch compute shader kernels and set parameters in bulk for the GPU simulation steps.

(There are many additional private fields—timing, kernel IDs, shader parameter IDs, native lists for source caching, job handles, and references to other systems—omitted above for brevity. See source for complete list.)

Properties

  • public static float SeaLevel { get; }
    Global sea level as determined by constant-depth water sources. Read-only.

  • public int WaterSimSpeed { get; set; }
    Multiplier controlling how many simulation iterations to run per update. Setting to 0 pauses simulation.

  • public float TimeStepOverride { get; set; }
    Optional override for the computed timestep. If > 0 the system uses this instead of its dynamic time step.

  • public bool Loaded { get; }
    True if the water system has loaded and initialized its textures/readers and is ready.

  • public bool UseActiveCellsCulling { get; set; }
    When true (default) the system culls simulation to "active" tiles for performance.

  • public int2 TextureSize { get; }
    Returns the current water texture resolution (m_TexSize).

  • public RenderTexture WaterTexture { get; }
    Primary water texture (holds per-cell depth/pollution/aux data).

  • public RenderTexture WaterRenderTexture { get; }
    Rendered velocity/auxiliary texture used during simulation and as previous frame input.

  • public bool BlurFlowMap { get; set; }
    Whether the downscaled flow texture is blurred during the flow map generation.

  • public bool FlowPostProcess { get; set; }
    Whether post-processing of flow (speed scaling and display filters) runs.

  • public int FlowMapNumDownscale { get; set; }
    Number of downscale passes used to build the flow texture (0 = none, up to MAX_FLOW_DOWNSCALE). Setting updates global shader textures/texel sizes.

  • public Texture FlowTextureUpdated { get; }
    Convenience: returns the final flow texture (either the selected downscaled texture or the main WaterRenderTexture if no downscales).

  • public float CellSize { get; }
    Cell size in world units used by the simulation grid (7f).

  • public float2 MapSize { get; }
    Overall map size in world units computed from CellSize * texture dimensions.

  • public int GridSizeMultiplier { get; set; }
    Exponent multiplier used to derive GridSize (default 3). Influences simulation tiling.

  • public int GridSize { get; }
    Computed simulation tile size = 32 * (1 << GridSizeMultiplier).

  • public float MaxVelocity { get; set; }
    Clamp for maximum flow velocity used by compute shader (default 7f).

  • public int MaxSpeed { get; set; }
    Integer determining simulation speed scaling used by bookkeeping (set externally).

  • public int SimulationCycleSteps { get; }
    Number of substeps used when adding water sources in a simulation cycle (returns 3).

  • public int2 m_ActiveGridSize { get; private set; }
    Grid size in tiles (TextureSize / GridSize) currently used for active-tile computations.

  • public bool IsAsync { get; set; }
    Flag indicating whether the water system should operate asynchronously (controls certain readbacks/tasks).

Constructors

  • public WaterSystem()
    Default constructor. The system is constructed by the ECS world. Actual initialization of shaders, textures and native resources happens in OnCreate().

Methods

  • [Preserve] protected override void OnCreate() : System.Void
    Initializes compute shader kernels, command buffer, creates textures and native lists, obtains references to Simulation/Terrain/Snow/Soil systems, and creates entity queries used to gather sources and parameters. Call order: InitShader(), InitTextures(), allocation of readers and buffers.

  • [Preserve] protected override void OnDestroy() : System.Void
    Cleans up GPU/CPU resources: disposes readers, native lists, compute buffers, command buffer and RenderTextures. Resets shader global params and sea level.

  • [Preserve] protected override void OnUpdate() : System.Void
    Runs every ECS update: completes source-gathering JobHandle, schedules a new SourceJob to collect WaterSourceData into native caches, updates save readback, and completes active-reader dependencies.

  • public void OnSimulateGPU(CommandBuffer cmd) : System.Void
    Entry used by the rendering/GPUSystem driver. If Loaded and properly sized, it will call Simulate(cmd) to run the GPU simulation steps.

  • private void Simulate(CommandBuffer cmd) : System.Void
    High-level simulation loop run on GPU: handles terrain-change timeouts, performs EvaporateStep, SourceStep, VelocityStep, DepthStep and CopyToHeightmapStep (and readback scheduling). Advances internal simulation frame counters and manages NewMap/restore behaviour.

  • private void InitTextures() : System.Void
    Allocates m_Water textures (RenderTextures), sets up compute buffers (m_Active), creates/initializes SurfaceDataReaders for depths and velocities, and marks the map as new.

  • private void InitShader() : System.Void
    Loads compute shader from the asset database, finds kernel indices and caches shader property IDs used throughout the simulation.

  • private void BindTextures() : System.Void
    Sets global shader textures and texel-size vectors used by water rendering (colossal_WaterTexture, colossal_FlowTexture, etc.).

  • private void Reset() : System.Void
    Zero-initializes the main water texture via compute shader Reset kernel.

  • public void ResetToSealevel() : System.Void
    Checks water source prefabs for constant-sea-level sources and resets the whole map to the determined sea level (calls ResetToLevel).

  • private void ResetToLevel(float level) : System.Void
    Sets the entire water texture to a given level using a compute shader kernel that samples terrain height to create a border-aware fill.

  • private void ResetActive(CommandBuffer cmd) : System.Void
    Resets the GPU active tile buffer (m_Active) via the ResetActive compute kernel. Usually called when grid size or other parameters change.

  • private void SourceStep(CommandBuffer cmd) : System.Void
    Applies water sources (point sources, constant-depth sources and border-add operations) from the last frame source cache to the water texture via Add/AddConstant/AddBorder compute kernels. Also updates global sea level if constant-depth sources are present.

  • private void EvaporateStep(CommandBuffer cmd) : System.Void
    Runs evaporation/soil-water interaction kernels. Prepares list of active tile indices, dispatches Evaporate compute kernel and writes soil-water outputs. Handles re-allocating active buffers if GridSize changed.

  • private void VelocityStep(CommandBuffer cmd) : System.Void
    Computes water velocities (wave propagation) using VelocityUpdate kernel. Produces WaterRenderTexture and the first downscaled flow texture.

  • private void DepthStep(CommandBuffer cmd) : System.Void
    Computes depth (height) from velocities using DepthUpdate kernel, performs flow downsampling and optional blur/postprocessing, and schedules readbacks for active tiles and depth/velocity readers.

  • private void CopyToHeightmapStep(CommandBuffer cmd) : System.Void
    Copies computed water data into terrain/heightmap-conformant outputs for the WaterRenderSystem/terrain integration.

  • private void UpdateGPUReadback() : System.Void
    Processes pending AsyncGPUReadback for the m_Active compute buffer. When readback completes, the CPU-side m_ActiveCPU is updated.

  • private void UpdateSaveReadback() : System.Void
    Processes pending GPU readback for save operations. On completion it calls JobSaveToFile to persist the float4 buffer.

  • public SurfaceWater GetDepth(float3 position, NativeArray<SurfaceWater> waterMap) : SurfaceWater
    CPU-side bilinear sample of water depth/pollution from a SurfaceWater array (usually filled via GetDepths). Returns interpolated SurfaceWater struct for arbitrary world position.

  • public NativeArray<SurfaceWater> GetDepths(out JobHandle deps) : NativeArray<SurfaceWater>
    Returns the CPU array containing water depths and sets a JobHandle that must be respected by callers (deps) for synchronization.

  • public WaterSurfaceData GetSurfaceData(out JobHandle deps) : WaterSurfaceData
    Returns a struct with pointers/arrays that represent the GPU-readback surface data for depths (and related metadata). Caller must respect returned deps.

  • public WaterSurfaceData GetVelocitiesSurfaceData(out JobHandle deps) : WaterSurfaceData
    Same as GetSurfaceData but for velocities/downscaled flow data.

  • public void AddSurfaceReader(JobHandle handle) : System.Void
    Register a job handle as a reader that depends on depth data (synchronizes with m_depthsReader).

  • public void AddVelocitySurfaceReader(JobHandle handle) : System.Void
    Register a job handle as a reader that depends on velocity/flow data.

  • public void AddActiveReader(JobHandle handle) : System.Void
    Register a job handle as a reader that depends on active-tile array readback.

  • public static float CalculateSourceMultiplier(WaterSourceData source, float3 pos) : float
    Utility that computes a normalization multiplier for a water source so that distributed additions across cells sum to the expected amount. Warns if a source radius is too small.

  • public static int2 GetCell(float3 position, int mapSize, int2 textureSize) : int2
    Translates world position to discrete texture cell coordinates.

  • public SurfaceWater GetDepth(float3 position, NativeArray<SurfaceWater> waterMap)
    (Bilinear sample helper, described above.)

  • public unsafe void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Serializes key counters and the water texture into the provided writer. Uses an async GPU readback into a NativeArray then compresses the float4 buffer before writing.

  • public unsafe void Deserialize<TReader>(TReader reader) where TReader : IReader
    Deserializes the saved water state, restoring water textures from serialized float4 arrays, reinitializing readers/buffers and re-binding textures. Handles multiple saved-version formats.

  • public void SetDefaults(Context context)
    Sets initial defaults when a brand-new map is created: clears readback counters, resets state and binds textures.

  • public void Save()
    Triggers an async GPU readback of the water texture for saving; pauses simulation while save is outstanding.

  • public void Restart()
    Resets internal active/tile buffers and sets the water texture contents to zero using a compute shader pass.

  • public void JobLoad()
    Placeholder in code (NotImplementedException) in provided source—intended for async job-based loading.

  • private void JobSaveToFile(NativeArray<float4> buffer)
    Placeholder (NotImplementedException) in provided source—intended to write out saved float4 data to disk.

(There are many additional helper structs and small internal methods—SourceJob, ReadCommandHelper, TypeHandle, WaterSourceCache, QuadWaterBuffer.CreateRenderTexture/Init/Dispose—that are integral to the system. See source for full low-level details and job logic.)

Usage Example

// Example: access the WaterSystem from a mod and trigger a sealevel reset
var world = World.DefaultGameObjectInjectionWorld; // or your World instance
var waterSystem = world.GetExistingSystemManaged<Game.Simulation.WaterSystem>();

if (waterSystem != null && waterSystem.Loaded)
{
    // Pause simulation, reset water to detected sea level (from constant-depth sources)
    waterSystem.WaterSimSpeed = 0;
    waterSystem.ResetToSealevel();

    // Or read depths (synchronize properly with JobHandles):
    JobHandle deps;
    var depths = waterSystem.GetDepths(out deps);
    deps.Complete(); // ensure readback is finished before accessing depths on CPU
    // sample depth at some world pos:
    var pos = new Unity.Mathematics.float3(100f, 0f, 200f);
    var sample = waterSystem.GetDepth(pos, depths);
    UnityEngine.Debug.Log($"Depth at {pos.x},{pos.z} = {sample.m_Depth}");
}

Notes and tips: - Many operations are GPU-driven. When querying CPU-side data (depths, velocities, active tiles) always respect the JobHandle / async-readback completion before reading NativeArray contents. - Changing FlowMapNumDownscale updates global shader textures; call it on main thread. - If you modify GridSizeMultiplier or GridSize at runtime the system may reallocate buffers and wait for pending readbacks—be careful to synchronize. - Serialization includes compression; saved data must match the current texture size to be safely loaded (mismatches are warned and skipped).