Skip to main content
← Roadmap
🌊 Oceanology ProIn Progress6.0.0

Included in Oceanology Pro and Oceanology Lite.

Rebuilt swimming system

One component on any character: swim, wade, dive, sprint, surface-lock, breathe, drown, and ragdoll into a corpse that drifts on the waves — in multiplayer, on every water body type.


Swimming in Oceanology Pro is one component. Drop UOceanologySwimmingComponent on any ACharacter and it swims: no buoyancy component, no pontoons, no sockets, no input rewiring. It swims through the engine's own MOVE_Swimming, so every stroke stays inside CharacterMovement's prediction and replication instead of fighting it. The system now lives in its own runtime module, OceanologySwimming, split into four objects with strictly one-way dependencies: the component owns the state machine, the forces and the config, a wave sampler owns every water query, a voxel math object owns the body geometry, and a ragdoll object owns the physics handover. None of the three helpers knows what a water body is, which is why each of them can be driven by anything that can answer "what is the water surface Z here".

How the swimmer finds the water

Entering a water body's collision volume only arms the component. Immersion alone decides what happens next, so a brush that also covers the wadeable shallows never drops a character straight into MOVE_Swimming. The infinite ocean has no overlap volume at all and is polled in tick. When several bodies overlap, the sampler picks the one the character is most immersed in and skips exclusion volumes. Every body type - ocean, lake, river and custom - is read through the same TryQueryWaterInfoClosestToWorldLocation call the renderer and the buoyancy path use, so the surface the swimmer floats on is the surface you can see, attenuated against the same per-location depth.

Immersion is measured on the animated body

  • The body is sampled as a real 3D voxel grid: four columns at the body-box quartiles by five spheres tall, twenty probes in total.
  • The grid is sized from the skeletal mesh's physics-asset bounding box in the reference pose, not from the capsule, and rides the mesh's live world scale.
  • It rotates with the animated pose and translates with the align bone, so a horizontal swim pose lays the stack flat on the water instead of standing it upright through the water column.
  • Each voxel queries the surface at its own XY, and its submerged fraction is a true spherical-cap volume ratio, not a depth guess.
  • The top row is measured separately as the head. That is what sets the Submerged tag and drains breath.
  • State decisions ride a low-passed swell, and swim start and stop use separate immersion thresholds, so one passing trough cannot flicker the state.

The float law

Vertical motion is a single blend applied as ordinary predicted movement input. Well below the flotation line the player owns the climb and the dive. At the line a damped spring takes over, with the buoyancy ratio's excess over one as its stiffness and the vertical water drag as its damping, pulling up from underneath and pushing back down from above. That spring supplies the gravity MOVE_Swimming does not have, so a held swim-up at the surface rides the waves instead of climbing into the air. A hard apex clamp sits above it and tracks a receding wave by feeding forward the surface's true fall rate, which is why a short steep wave no longer strands the body above the water. Pitch and roll can follow the local wave slope from a three-point surface sample, yaw is driven from horizontal velocity with a hold threshold so a stopping swimmer never snaps, and automatic scaling derives the body-dependent tuning from the capsule size, the world gravity and the movement mass.

State is gameplay tags, not a pile of bools

  • Oceanology.Swimming.State.Dry, .Wading and .Swimming are mutually exclusive, with exactly one writer.
  • Oceanology.Swimming.Submerged, .Drowning and .Drowned ride the same authority-written container.
  • Oceanology.Swimming.Control.Sprinting, .SurfaceLocked and .Ragdoll live in a second container that the owning client predicts, so a state update can never revert a toggle the player just made.
  • Tags are registered natively, so there is no DefaultGameplayTags.ini entry to add.
  • Every transition side effect is derived from one before-and-after container diff, and the same funnel runs on the authority and on clients.
  • OnSwimmingTagsChanged reports the added and removed delta on every machine, ready to forward into GAS, a HUD or an ability gate.

Ragdoll that drifts instead of sinking

SetRagdoll hands the body to its physics asset. The intent replicates and the handover runs locally on every machine, simulated proxies included. With drift enabled the physics asset's own rigid bodies become the voxels: each gets a sphere submerged fraction against the animated surface at its own XY, buoyancy from that fraction, water drag damping toward the surface's own vertical motion, and a downhill push along the wave face. Forces go in as acceleration changes, so a heavy pelvis and a light hand float alike rather than letting mass distribution decide who sinks. The authority keeps the capsule under the drifting corpse so the replicated location follows it, and on release the capsule is traced down and stood on the surface under the body. Drowning to death can trigger the whole thing automatically, and Revive stands the character back up.

What you bind

  • Controls: SwimVertical, SwimMoveForward, SetSwimSprint, SetSurfaceLockedSwimming, SetRagdoll and Revive. The movement path is predicted, with no RPC of its own.
  • Events: entered and exited water with impact speed, wading, swimming, submerged, surfaced, sprint, surface lock, ragdoll, drowning start and stop, drowned and revive.
  • Counter events: breath and drowning each carry seconds, the configured maximum and a 0 to 1 fraction, so a HUD bar binds once instead of polling and stays correct on clients.
  • Animation: derive your AnimBP from UOceanologySwimmingBaseAnimInstance and read the thread-safe live data object from the thread-safe update.
  • Cosmetics: the component broadcasts and never plays anything. Splashes, bubbles and loops are yours to wire.
  • Read-only consumers can go through IOceanologySwimmerStateSource without linking the swimming module at all.

Versus Oceanology NextGen

Oceanology NextGenOceanology Pro
Runtime stateAround twenty-eight replicated properties, each with its own OnRep, plus a separate swimming enumTwo replicated gameplay-tag containers plus two replicated counters, with one shared transition diff
Immersion measurementCapsule-based immersion against a single sampled surfaceTwenty-probe voxel volume sized from the mesh physics asset, following the animated pose
Module layoutOne large component inside the main runtime moduleIts own OceanologySwimming module, with water reading, body geometry and ragdoll physics as separate objects
CosmeticsBubble emitters, sounds and underwater effect properties built into the componentEvents only, so effects are authored where the rest of your game's effects live
RagdollNot part of the swimming componentReplicated ragdoll control with per-body water drift and an authority capsule follow
ComponentUOceanologySwimmingComponent, shown as Oceanology Swimming
ModuleOceanologySwimming, runtime, loads at PostConfigInit
Movement modeEngine MOVE_Swimming, CharacterMovement-predicted
Voxel grid4 columns x 5 spheres = 20 probes, sized from the mesh physics asset
Swim start / stop immersion0.7 / 0.55 (hysteresis)
Swim speed / sprint speed300 / 600 cm/s
Buoyancy ratio / vertical drag1.35 / 3.0 per second
Resting waterlineSwimApexAllowance, -20 cm at mannequin scale
Breath / recovery / drown to death20 s, 3x refill rate, 10 s
Wade speed at neck depth0.5x walk speed, scaled continuously with depth
Max wave tilt / interp speed18 degrees / 6.3
Out-of-water exit delay1.5 s, to stop trough porpoising
Hydrodynamic dragCoefficient 0.005, deceleration = coefficient x excess speed squared
Native gameplay tags9, under Oceanology.Swimming
Replicated properties2 tag containers plus 2 counters, push-model

This is one entry on the Galidar roadmap. For what already shipped in each release, see the Changelog.