Description

Summary

Water can sporadically disappear in World Partition maps that have multiple spatially loaded AWaterZone actors.

FWaterViewExtension::UpdateGPUBuffers() builds the WaterZoneData and WaterZoneViewData arrays densely by iterating FWaterBodyManager::ForEachWaterZone(), which skips free slots. The shaders, however, index these buffers by the sparse WaterZoneIndex, which comes from a TSparseArray. When zone indices are not tightly packed, zones read the wrong zone's data, or read past the end of the zone section.

Details

  • FWaterBodyManager::WaterZones is a TSparseArray.
  • AddWaterZone uses EmplaceAtLowestFreeIndex.
  • RemoveWaterZone uses RemoveAt(GetWaterZoneIndex()).
  • Shrink() only trims trailing free slots, so holes in the middle remain when a lower-index zone is unregistered while a higher one stays loaded. This is common with streaming, depending on load/unload order. Stale weak pointers are skipped too.
  • WaterViewExtension.cpp, UpdateGPUBuffers(): WaterZoneData.Emplace(...) and WaterZoneViewData.Emplace(...) run inside ForEachWaterZone, so the arrays are packed.
  • Water bodies are handled correctly: WaterBodyData.SetNumZeroed(WaterBodyManager->MaxWaterBodyIndex()), then WaterBodyData[GetWaterBodyIndex()]. There is no equivalent for zones.
  • Shaders/Private/WaterDataFunctions.ush uses the raw zone index as an offset:
  • GetWaterZoneData: ZoneDataOffset + InWaterZoneIndex * PER_WATERZONE_DATA_SIZE
  • GetWaterZoneViewData: (InWaterZoneIndex * NumViews + ViewIndex)
  • Result: wrong zone extents, height extents and ground Z, so water info decoding fails and water disappears.

The issue is still present in UE5 Main and UE6 Main.

Suggested fix (provided by licensee)

Add a MaxWaterZoneIndex() helper analogous to MaxWaterBodyIndex().

  • Zero-fill WaterZoneData to MaxWaterZoneIndex entries and WaterZoneViewData to MaxWaterZoneIndex * NumViews entries.
  • Write each zone at WaterZoneIndex, and each view entry at WaterZoneIndex * NumViews + ViewIndex.
Steps to Reproduce
  1. Create a World Partition map.
  2. Place multiple AWaterZone actors that are spatially loaded (not always loaded), each containing multiple AWaterBody actors.
  3. Move around so zones stream in and out, such that a lower-index zone is unloaded while a higher-index zone stays loaded.

Result: water in the remaining zone(s) renders incorrectly or disappears.

Expected: water renders correctly regardless of zone streaming order.

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-402764 in the post.

0
Login to Vote

Unresolved
ComponentUE - Graphics Tools - Terrain - Water
Affects Versions5.7.4
Target Fix5.8.5
CreatedOct 14, 2026
UpdatedOct 19, 2026
View Jira Issue