Skip to content

Troubleshooting

If you hit something not listed here, check the Discord.

  • Confirm bEnableFFT is true on the GridManager (or BP_DynamicRealWater).
  • If a WaveDataAsset is assigned, that asset’s bEnableFFT overrides the actor’s properties.
  • Check WaveAmplitude is non-zero on at least one cascade.

Waves don’t appear on a dedicated server’s PIE window

Section titled “Waves don’t appear on a dedicated server’s PIE window”

By design: dedicated servers skip ocean visual simulation entirely (waves are visual-only and cost compute the server doesn’t need). Use a listen server or run as a client to verify visuals.

  • Wave time is synchronized via ReplicatedSpectrumTime once on first replication. A client that joins before the server has ticked will sync on the following frame.
  • The GridManager replicates automatically: no toggle. If sync still fails, verify the actor isn’t being spawned with bReplicates overridden in a subclass or level Blueprint.
  • Check MaterialType on each shape. Anything denser than 1025 kg/m³ sinks. Floating materials: Wood (800), Plastic (950), HighDensityFoam (450). Sinking: Steel (7850), Concrete (2400), Glass (2500).
  • Verify your shapes match the actual mesh volume. Undersized shapes underestimate buoyant force.
  • Use Subtractive shapes (or MaterialType = Air) for cabin interiors so the hull isn’t computed as a solid block.

See the hull approximation guide for the full workflow.

  • Increase HeaveDampingCoefficient on the BuoyancyComponent (default 0.7, up to ~1.5 is reasonable).
  • Confirm bEnableHeaveDamping = true.
  • Reduce SlammingCoefficient (default 1.0). V-hulls usually want 1–2; flat-bottoms want 2–4 if you want the hard slam, lower otherwise.
  • Set bEnableSlamming = false to disable entirely.

I want wakes / ripples to push my floating object around (or not)

Section titled “I want wakes / ripples to push my floating object around (or not)”

Buoyancy samples both the FFT ocean heightmap and the interaction layer (wakes, ripples, splashes). The interaction contribution is gated by InteractionHeightMultiplier on the BuoyancyComponent (default 1.0).

  • Want stronger reaction to wakes: increase InteractionHeightMultiplier above 1.
  • Want ripples to be visual only: set InteractionHeightMultiplier = 0. Buoyancy then samples the FFT heightmap exclusively.

My object inside a Pool / Lake is still being affected by ocean buoyancy

Section titled “My object inside a Pool / Lake is still being affected by ocean buoyancy”
  • The buoyant actor must overlap the WaterBody’s WaterVolume box. The WaterBody sets OverlappingWaterBody on overlap; without overlap, the BuoyancyComponent samples the ocean RT.

My vessel won’t turn or turns sluggishly

Section titled “My vessel won’t turn or turns sluggishly”
  • Increase TurnAssistMultiplier on VesselMovementComponent. Default 1.0 is physically accurate; large vessels (> 50 m waterline) typically need 5–20 for responsive feel.
  • Confirm a Rudder-type ControlSurfaceDataAsset is in VesselDataAsset → ControlSurfaces, with positive RudderArea and non-zero MaxDeflection.
  • Confirm at least one Engine / Jet / Sail PropulsionDataAsset is in VesselData → PropulsionSources.
  • Check MaxPowerKW > 0 for engines.
  • Easiest path: copy BP_Runabout or BP_Dinghy data assets and modify rather than building from scratch.

Input stops working after exiting a vessel

Section titled “Input stops working after exiting a vessel”
  • Input setup must run via Restart() / OnRep_Controller, not PossessedBy. If you’ve subclassed and overridden one of these, ensure you call Super::.
  • For seat-based control, verify the seat’s SeatType = Helm. Passenger seats do not relay input to the vessel.

Other clients don’t see my boat’s wake

Section titled “Other clients don’t see my boat’s wake”
  • Stroke replication uses Multicast Unreliable (intentional: strokes are visual). Occasional drops are expected.
  • Strokes age out at 3 seconds; clients joining mid-game won’t replay older strokes.
  • Persistent absence usually means PhysicsBodyComponent.bEnableWaterInteraction = false on the server.
  • The Pool boundary mask uses Unreal’s Global Distance Field. Enable Project Settings → Rendering → Mesh Distance Fields → Generate Mesh Distance Fields (r.GenerateMeshDistanceFields = 1).
  • The pool’s surrounding geometry must have distance fields generated (default for static meshes when the project setting is on).
  • Tune BoundaryDistanceThreshold (default 25 cm). Lower tracks geometry tighter but can leave gaps if the GDF is coarse.
  • Confirm bEnableCaustics = true on the WaterBody.
  • Adjust CausticsStrength on the assigned WBVisualDataAsset.

Geometry isn’t masking the water surface

Section titled “Geometry isn’t masking the water surface”
  • Place exactly one WaterMaskingManager in the level. Without it, surface mask components are inert.
  • Verify the actor with SurfaceMaskComponent has a valid MaskMesh assigned.
  • The mask follows the player camera; geometry farther than SurfaceMaskCoverage (default 6400 cm) from the camera won’t be masked.