Water System API
The WaterSystem class provides global access to real-time water state, simulation parameters, and environment synchronization.
It also includes utility methods for underwater checks, surface data access, and network synchronization.
Water State & Underwater Detection
WaterSystem.ForceUpdateWaterSettings()Forces immediate reinitialization or refresh of water settings for the specified category. This method must be called manually when any water parameters are changed at runtime — for example, FFT wind strength, caustic resolution, or volumetric lighting quality.
Usage example:
WaterSystem.Instance.CausticStrength = 4; //water system settings
KWS_Ocean.Instance.WindSpeed = 4; //ocean settings
WaterSystem.QualitySettings.UseScreenSpaceReflection = true; //quality settingsAfter changing parameters that affect GPU data (such as FFT wind, caustic resolution, or reflection buffers), you need to manually force an update to apply the changes:
WaterSystem.ForceUpdateWaterSettings(WaterSystem.WaterSettingsCategory.Ocean |
WaterSystem.WaterSettingsCategory.Caustic |
WaterSystem.WaterSettingsCategory.Reflection);You can also refresh all categories at once:
WaterSystem.ForceUpdateWaterSettings(WaterSystem.WaterSettingsCategory.All);However, it’s recommended to update only the categories that actually changed, since unnecessary reinitialization may cause short GPU stalls or texture reallocations
Purpose:
Recreates or re-uploads dependent GPU textures (FFT spectra, caustic maps, lighting buffers, etc.)
Ensures updated values take effect immediately without restarting the scene
Used by in-game editors or dynamic weather systems that modify water parameters in real time
Returns true if the active camera is partially submerged (intersecting the water surface). Used by underwater effects, refraction, and post-processing systems to determine blending regions between above/below-water rendering.
Returns true if the active camera is fully underwater. When the state transitions from IsCameraFullUnderwater to IsCameraPartialUnderwater, the water drops effect on the camera lens is automatically triggered
Checks if a world-space position is below the current water surface (ocean or dynamic zone). Returns true if the position’s Y coordinate is lower than the evaluated water height at that location.
Use cases:
Determining if an object or player is submerged
Triggering underwater effects or sound zones
API – Water Surface Query System
KWS2 allows sampling real-time water surface data directly from GPU simulation (both FFT ocean and dynamic waves).
This is done asynchronously through the TryGetWaterSurfaceData() method, which collects all requests from different scripts, batches them into a shared compute buffer, and processes them inside the water rendering loop (using compute shader).
How it works
Every frame, different scripts can send variable numbers of water queries (e.g., 3 objects one frame, 2 objects the next).
To guarantee data consistency and avoid stale GPU results, each request uses an interface container IWaterSurfaceRequest.
This container is automatically updated by the water system every frame, so you only need to assign query positions and read back the results.
Available container types:
WaterSurfaceRequestList — dynamic list (for variable counts of objects)
WaterSurfaceRequestArray — fixed-size array (best for stable object counts)
WaterSurfaceRequestPoint — single-point query (minimal overhead)
Example usage
Each frame, the system automatically updates _request.Result[] with the most recent simulation data.
Since all requests are processed asynchronously on the GPU, results are typically available with a 1-frame delay.
Calculating normals manually
Since normals are not always needed, they are not computed by default to avoid unnecessary GPU overhead (calculating them directly in compute would roughly quadruple processing cost). If normals are required, you can approximate them manually using small position offsets and finite differences:
Performance notes
All queries are GPU-driven and handled in a single compute shader dispatch per frame.
Returned data is asynchronous — results are updated automatically in the linked container.
The system scales efficiently even with hundreds of simultaneous queries.
Advanced usage – NativeArray & Job System integration
KWS2 also supports sending surface queries directly through NativeArray buffers using the Unity Job System.
This allows asynchronous sampling of water data outside the main thread — for example, when updating object positions in IJobParallelForTransform jobs or handling large batches of floating objects.
This feature is especially useful for:
Mass buoyancy simulations
Parallel movement updates (hundreds of transforms per frame)
Reducing main-thread synchronization and latency
However, the API is still experimental and subject to change. For reference and working examples, see:
Script:
Assets/KriptoFX/WaterSystem2/DemoScenes/Data/Scripts/ParallelTransformTest.cs
Demo Scene:
BuoyancyJobParallel
These demonstrate how to build NativeArray-based requests, send them directly to the water system, and process the results asynchronously within the job loop.
Network & Simulation Control
When true, the water simulation (FFT ocean waves only) uses a shared network time instead of the local system clock. Ensures identical ocean wave motion across clients in multiplayer environments. Dynamic waves are non-deterministic (they depend on the client's FPS rather than time), so they can'’t be synchronized. However, if the data doesn't change (for example, a water source) or the ocean is synchronized, then dynamic waves will have approximately the same parameters for all clients (but it's not guaranteed).
The network-synchronized time value used when UseNetworkTime is enabled.
Usually set by the game’s server or synchronization system before each frame update.
When true, buoyancy calculations are still executed on the GPU, even if the ocean is not currently visible to any camera. This is useful for headless or background simulations (e.g., physics updates, network or server-side logic) where rendering is disabled but floating objects still need accurate buoyancy forces.
The feature does not affect rendering or synchronization — it simply keeps the buoyancy compute shader active regardless of water visibility.
Last updated