Basic commands in editor

Material M_FD_Surfacewater

I have been rewriting this part completely new in C++. So at the moment a lot of the following is out of date.

  • Culvert at dike
    To discharge water from island to sea
  • Pumping station with pipes
    To discharge water from island to sea
  • Ditches
  • Discharge water to Pumping-station of culvert at dike
  • Weirs
    To control waterlevel ditch
  • Culvert in ditch
    When ditch has to cross road
  • Lakes / surface water
    For storage of surplus of rainfall
  • Sewer pipe
  • Storage settling basin (BBB)

The dynamic water system on land is programmed as a blueprint.
FD_Surfacewater contains both the logic and the assets of the water system. The backbone of the FD_Surfacewater  is a spline with points. The points represent a change in the water system, for example: input discharge, different structure (pipe, channel, weir..), different dimension. So each point (=Node) is connected with the database WaterSystemData. So in between 2 points (=branch) of the backbone spline, everything is the same, based on the information of the downstream point.. Spline and point represent the bedlevel of the structure.
Index 0 spline is downstream

Al the programming is done in the so called construction script. This is a cool feature of Unreal Engine.  Al programmed calculations can be done in the editor. It is for example not necessary to run the game, to see what waterlevels will occur. They are already calculated in the editor.

Formulas used for calculation water levels

Some general Notes:

  • The basis of the watersystem is a spline. Between 2 nodes the structure is the same. The location of the spline is the bedlevel.
  • FD_Surfacewater  is one line with no branches and has a fixed direction of flow.
  • A dendritic system is possible, because the 3D world may contain different FD_Surfacewater  which are connected at points. When calculation a dendritic system the sequence of making calculations is important.
  • Strategy for calculating the water-system.We assume a stationary flow. So new calculations are only made when changes are made to the water-system. In the future calculations will be made per time-step and change in storage will also be taken into account.
    Link to page with formulas used
  • To get access to the information, or to change information menu are used.
    Link to page Navigation
  • Internal Unreal uses centimeters, the
    FD_Surfacewater uses m
  • Backbone of FD_Surfacewater is the WaterDataStruct which stores all data (also calculated data) for each branch.

Connect side branches

  • Information on side branch is stored in [ConnectionLeft] and/or [ConnectionRight]
  • In FD_GameMode: FD_WaterSystemsref and FD_WatersystemName. Note This does not work in constructionscript ? So it should be a separate function in the constructionscript.
  • New function Find_Side_Branches
  • Changed variable InputDischarge to a 2dvector. x = de input branch, y is the input from sidebranches

Design Manhole / Sewer

  • If 2 pipes don’t have the same bedlevels, the difference in height is stored in With_Diameter_m.y. Adding this height is only applied the x downstreampoint
  • Manhole is not a separate branch, but is generated when 2 culvert pipes branches connect.
  • The check on manhole is made when type is culvert. If type_down also is a culvert, a manhole can be added.
  • Switch to add manhole is :
    When diameter pipes is different, manhole is added automatically
    When diameter pipes are the same, the following switch is used.
    Slope X = 1 add manhole, Slope X = 0 no manhole  
  • A Boolean variable Manhole  is defined.
  • Manhole is always a rectangle, with max 4 pipes connected.  So 2 other BP_watersytems could be connected to the manhole.
  • Alle dimensions in m
  • When function manhole is activated the following information is defined:
    – bedlevel, based on 4 connections
    – D1, D2 (left), D3, D4(right)
    – Width manhole based on D1 and D4.  Width = Max D1 / D3 + 0,6 m
    – Length manhole based on D2 en D4. Length = Max D2 / D4 + 0,6 m
    – Length manhole / 2 = reduction length (m)
    – Surfacelevel is de highest surfacelevelworld of the 4 connections
  • Manhole is activated before the pipe is drawn. This because the reduction length.
  • Information from the array is also necessary for the Reduction Length for ending and starting pipe.

Design weir

  • Exists of 3 parts, left – middle (=crest) – left
  • Width_Diameter_m.x = width weir.
  • Width_Diameter_m.y = width sides

Blueprints used:

Share Button



Share Button



Share Button




Share Button

Underwater life





Share Button





Share Button


How to get the unreal watersystem programmable?

Documentation water

Different classes used for water


AWaterBody (file WaterbodyActor.h)

AWaterBodyRiver (file WaterBodyRiverActor.h)
This file also includes URiverGenerator





virtual void InsertPoint(int32 Index, float t, bool bClosedLoop) override;
/** Update point at index by lerping metadata between previous and next key values */
virtual void UpdatePoint(int32 Index, float t, bool bClosedLoop) override;
virtual void AddPoint(float InputKey) override;
virtual void RemovePoint(int32 Index) override;
virtual void DuplicatePoint(int32 Index) override;
virtual void CopyPoint(const USplineMetadata* FromSplineMetadata, int32 FromIndex, int32 ToIndex) override;
virtual void Reset(int32 NumPoints) override;
virtual void Fixup(int32 NumPoints, USplineComponent* SplineComp) override;

FInterpCurvefloat is a struct


Share Button


List of the different water-systems on the island.  Wil be used for the instructural design, design island and assets

First attempt to build a water system in Unreal

  1. Waves at sea
  2. Tide at sea
  3. Currents at sea
    Erosion of beach
  4. Culvert at dike
    To discharge water from island to sea
  5. Pumping station with pipes
    To discharge water from island to sea
  6. Rainfall
    Is main source for supply of freshwater on the island
  7. Seepage
    From island to sea.
    From sea to groundwater.
  8. Groundwater
  9. Drainage pipes
  10. Ditches
    Discharge water to Pumping-station of culvert at dike
  11. Weirs
    To control waterlevel ditch
  12. Culvert in ditch
    When ditch has to cross road
  13. Lakes / surface water
    For storage of surplus of rainfall
  14. Sewer pipe
  15. Infiltration
    Infiltration sewer, Wadi, infiltration box, infiltration box
  16. Storage settling basin (BBB)
Share Button


I bougth the Procedural Nature Pack Vol.1

Tutorials for the nature Pack

There is also the free Open World Demo Collection


Share Button

Fluid Dynamics Formulas

General assumptions

  1. Flow is turbulent.
    So formulas of Manning, Chezy and Darcy-Weisbach can be used.
  2. Flow is sub-critical.
    So calculations of water-levels start downstream and goes upstream. At weirs super-critical flow may occur.
  3. Flow is steady
    Discharge is not changing rapidly. Of-course over time discharge (and thus water-levels etc) can change.
  4. Sea is salt water, on the island fresh water
  5. There are two main watersystems. The watersystem on the island and the sea (waves, tide, current). The connection between the two are by the culvert in the dike and seepage. High tide in combination with low water level on the island could make water flow from sea to the island. High tide can cause seepage to the land, low tide seepage to sea. Maybe in high tide in combination with big waves can cause water flowing over the dike to the island.
  6. Water enters the systeem by: rainfall and seepage.
  7. Water leaves the island through : Culvert in dike, pumping station, seepage and evapotranspiration.
  8. System is dendritic.
    So water has one direction to flow.

Calculations in FD_watersystems

  • For each branch waterlevel (ylevel) and Energylevel (Hlevel) are calculated at the beginning (.x) and end (.y) of the branch. This info is stored in WatersystemData.
  • Hlevel.x = Hlevel.y downstream branch.
  • yLevel.x = yLevel.y downstream branch. Consequence of this strategy is that when there is a significant change in dimension or discharge, a short branche is needed. In this short branch the transfer between the 2 different velocityheads takes place. With change in discharge this short branch is located downstream, with change in dimension this short branch is located upstream
  • Weir is an exception. Hlevel.x is calculated based on the crestlevel.
  • Over the length of a branch, the basic dimensions are the same, only the surfacelevel at x and y may differ. Exception is the connector, you have different width and slope downstream and upstream!!
  • CulvertRectangle: If downstreams  waterdepth < Height culvert : Type is converted to Trapezium. Note: With high velocities, water level will rise and the type maybe should be concerted back to culvertrectangle. This can be solved by splitting het culvert in several branches.
  • In a branch (between 2 points) discharge is always the same. 
  • 2 special branches when calculating. First is the outflow: Discharge = 0. Value in InputDischarge.x is the velocity in the receiving water. Second is the weir : There is a jump in HlevelWorld compared to the downstream waterlevel.
  • Weir is always assumed as free flow.  And as a short crest. Waterlevel .x and .y are the same.
  • Based on ylevel.x. Slope Hline is calculated. Hlevel.y is calculated.

Workflow calculation

In the case of type = trapezium

  1.  HlevelWorld_m.x = HlevelWorld.y previous branch
  2. yLevelWorld_m.x = yLevelWorld.y previous branch 
  3. Get Discharge from point upstreams
  4. Calculate Depth_m.x ,WettedArea.x, WetterPerimeter.x, HydraulicRadius.x, Velocity.x
  5. Calculate Hslope, dH, Time
  6. HlevelWorld_m.y = HlevelWord_m.x + dH
    ylevelWorld_m.y = yLevelWorld,x + dH
  7. Calculate Depth_m.y ,WettedArea.y, Velocity.y, VelocityHead
    ylevelWorld_m.y= HLevelWorld_m.y – VelocityHead
  1. Outflow down-streams is calculated separate
  2. Check if branch is weir. If weir calculate H above weir, convert to HlevelWorld_m.x = HlevelWorld.y.  yLevelWorld_m = CrestlevelLevelWorld_m + 2/3 * H.
  3. If branch is not weir
  4. If branch = connector; calculate average width and average slope
  5. Calculate Depth_m.x ,WettedArea.x, WetterPerimeter.x, HydraulicRadius.x, Velocity.x
  6. Calculate Hslope, dH, Time
  7. HlevelWorld_m.y = HlevelWord_m.x + dH
  8. ylevelWorld_m.y = yLevelWorld,x + dH
  9. Calculate Depth_m.y ,WettedArea.y, Velocity.y, VelocityHead
  10. ylevelWorld_m.y= HLevelWorld_m.y – VelocityHead

Culvert and Rectangle Culvert

  • dH is a 3d vector. x = dH outflow, y dH friction, z dH inflow
  • dH x outflow based on carnot
  • dH y friction based on Chezy, with coeff = k (m)
  • dH z inflow based on contraction coefficient of 0,6, so xi = 0,44
  • If branch downstream = culvert, dH x = 0
  • If branch upstream = culvert dH z = 0
  • Extra info needed is type up-streams and down streams. local_type_up and local_type_down
  • Extra info needed is W and H up and down if type is culvert. local_WH_up and local_WH_down
  • Hlevel.x culvert = Hlevel.y type_down + dH.x
  • Hlevel.y culvert = Hlevel.x + dH.y. So dh.z is not added yet
  • Ylevel.x and Ylevel.y are based on Hlevel.x .y – velocityhead
  • dH.x and dH.z are based on the type of the adjacent branch.
  • dH.x and dH.z is not yet calculated with Rectangle Culvert.


Area pipe

Chezy coefficient
Chezy energy slope

Manning energy slope
Slope energy line
Sharp crest free flow
Partially filled pipes
Share Button