Water buoyancy and gameplay
This chapter covers floating objects, kinematic wave followers, gameplay events, optional bridges, global tide, and the script-facing surface APIs.
Buoyancy
Add Water Buoyancy next to a Rigid Body and Collider. The physics system samples the unified WaterSurfaceRequestBus each step.
Buoyancy Settings
| Field | Purpose |
|---|---|
| Sample Points | Entity-local immersion probes; empty = auto 2×2×2 grid from collider AABB |
| Buoyancy Scale | 1.0 = exact Archimedes for displaced volume |
| Linear Drag / Angular Drag | Drag / damping in water |
| Flow Influence | Flow-field thrust coefficient |
| Wave Sample Mode | Full / Height Only / Still Water |
| Sleep In Still Water | Allow rigid body sleep once stable in calm water |
| LOD Tier Lock | Auto or force Tier A–D (Full ?Height Only ?Still ?Frozen) |
Boats usually need 6? manual sample points (bow / stern / beam). Too few points in shallow water cause launches—raise drag and add samples.
Requires the water body’s Affects Physics and /O3DE/Gems/Water/PhysicsEnabled. Floater must reside in an active streaming cell (oceans: AlwaysLoaded).
Sample Prefabs: AutomatedTesting/Prefabs/Water/BuoyantCrate, Driftwood, SimpleBoat.
Surface attachment
Water Surface Attachment follows waves kinematically (no rigid body)—buoys, markers, towed floats.
| Field | Purpose |
|---|---|
| Anchor Mode | Fixed Rest Point (moored) or Follow Entity XY (towed) |
| Align To Surface | Tilt up axis onto the wave normal |
| Smoothing Time | First-order lag seconds (0 = exact pin) |
| Out Of Water | Hold Last Position or Follow Rest Point when uncovered |
Script / C++: WaterSurfaceAttachmentRequestBus (SetRestAnchor, SetAttachmentEnabled, ?. Internally uses GetDisplacedSurfacePosition (Lagrangian rest XY ?displaced world point).
Events
Per floater ?WaterNotificationBus (addressed by floating EntityId)
| Event | Meaning |
|---|---|
OnEnteredWater | Crossed into water; carries water body id + sample |
OnExitedWater | Left water |
OnSubmersionChanged | Submerged fraction 0? (1/16 steps) |
Global ?WaterSystemNotificationBus
| Event | Meaning |
|---|---|
OnCameraEnteredWater / OnCameraExitedWater | Camera underwater transitions |
OnBodyEnteredWater | Same as enter, plus enterSpeedMps (splash gating) |
OnBodyExitedWater / OnBodySubmersionChanged | Global mirrors of per-body events |
Bridges
| Bridge | Role |
|---|---|
| SurfaceData | Publishes water / underwater / riverbank when Emits Surface Tags is on |
| Navigation3D | Registers active bodies as underwater regions for hybrid routing |
Particle (WaterParticleBridgeComponent) | Maps enter / exit / camera / submersion to OpenParticleSystem (optional Gem) |
Particle asset paths and thresholds live under /O3DE/Gems/Water/Particles/ (SplashParticleAsset, BubbleTrailParticleAsset, CameraBubblesParticleAsset, MarineSnowParticleAsset, SplashMinEnterSpeed, EffectLifetimeSeconds).
Tide and per-body control
| API | Effect |
|---|---|
WaterSystemRequestBus::SetGlobalTideOffset | Uniform still-water offset (usable ± a few meters; no mesh rebuild) |
| Body Affected By Global Tide | Opt out for mountain reservoirs |
WaterBodyRequestBus::SetWaterLevelOffset | Per-body still-water offset |
WaterBodyRequestBus::SetWavesEnabled | Runtime wave toggle (cutscenes) |
Script and C++ surface APIs
BehaviorContext category: water (Lua / Script Canvas / C++).
| Bus | Script-bound |
|---|---|
WaterSurfaceRequestBus | GetWaterSurfaceSample, height, IsPointUnderwater, flow, GetDisplacedSurfacePosition |
WaterSystemRequestBus | Get/SetWaterTime, ClearTimeSource, Get/SetGlobalTideOffset |
WaterBodyRequestBus | Set/GetWaterLevelOffset, SetWavesEnabled |
WaterSurfaceAttachmentRequestBus | Rest anchor, enabled |
| Notification handlers | Floater + system events above |
C++ only (not script-reflected): SetTimeSource, GetWaterInfoRaster, batch GetWaterSurfaceSamples, internal NotifyGlobalTideChanged.
Sample flags for queries: Default, HeightOnly, StillWater, IgnoreFlow (see
Core concepts).
#include <Water/WaterSurfaceRequestBus.h>
#include <Water/WaterSystemRequestBus.h>
Water::WaterSystemRequestBus::Broadcast(&Water::WaterSystemRequests::SetGlobalTideOffset, 0.4f);
bool underwater = false;
Water::WaterSurfaceRequestBus::BroadcastResult(
underwater, &Water::WaterSurfaceRequests::IsPointUnderwater, worldPosD);
Dry volumes and gameplay
Queries that fall inside a Water Dry Volume miss as if no water were present—useful for dry interiors inside a lake or ocean XY footprint. See Authoring#dry-volume.