public sealed class BuoyancySystemFloats every BuoyancyBody on the one surface everything else reads.
As a system
- Phase
- FixedUpdate
- Reads
- PhysicsBody
- Writes
- BuoyancyState
- Runs before
- PhysicsStepSystem
- Runs after
- PhysicsSyncSystem
Remarks
[35 § D10](../../docs/plan/35-water.md#d10-buoyancy-is-pontoons-over-jolt-evaluated-at-the-fixed-steps-water-time), and the whole of what this assembly is for. Per fixed step, per pontoon: ask the surface where it is, work out how much of the sphere is under it, and apply the force at the pontoon's own world position — which is what makes a hull pitch when somebody stands at the bow rather than bob level.
⚠ Before PhysicsStepSystem and after PhysicsSyncSystem, and both halves of that matter. Jolt accumulates forces and clears them at the step, so a force applied after the step is a force that is thrown away — a boat that sinks with the system visibly running. And a force applied before the sync is a force on a body the sync is about to create, which is the first frame of every boat lost.
⚠ It reads the simulation's water time off IWaterSurface and never its own GameTime. A force computed from a frame time changes when the frame rate does, which in a networked game is a client and a server disagreeing about where a boat is — [16](../../docs/plan/16-networking.md)'s determinism requirement applied to a force. WaterClockSystem is what advances that clock, and it does so in EarlyUpdate precisely so that this can read it.
⚠ Jolt has a buoyancy impulse of its own and it is deliberately not used. It takes a plane, which is exactly the approximation a wave surface is not — and using it would put a second definition of the water surface inside the physics engine, where § D2's seam test cannot reach it.
⚠ Ripples are not passed, and the omission is the design. The closed-form sum is exact and answerable at any time; a ripple field is a simulation whose state is its history, and a rollback re-simulating six ticks cannot ask it where the surface was. So the force a server computes and the force a client predicts are the same function of the same arguments. A wake that pushed a boat around would be a wake that desynced it.
Fields and properties (10)
public WaterDisturbances? DisturbancesWhere this step's wakes and splashes go, or null to produce none.
public float WakeSpeedHow fast a pontoon has to move through water before it makes a wake, in m/s.
public float SplashSpeedHow fast a pontoon has to enter the water before it splashes, in m/s.
public IWaterSurface SurfaceWhere the water is, and the clock it is at.
public SystemAccess Accesspublic int FloatingHow many bodies the last step floated — those with at least one wet pontoon.
public int PontoonsHow many pontoons it evaluated, across every body.
public int WetPontoonsHow many of those touched water.
public ReadOnlySpan<BuoyancyForce> ForcesThe forces the last body evaluated produced, for a debug draw.
public int LastCountHow many of Forces are the last body's.
Methods (3)
public BuoyancySystem(PhysicsScene scene, IWaterSurface surface)Floats every BuoyancyBody on the one surface everything else reads.
public override JobHandle Update(in SystemContext context, JobHandle dependency)Runs the system.
public void Step(World world)Applies one step's worth of buoyancy.
Used by (4)
- BuoyancyDebugDrawVixen.Water.Physics
- BuoyancyDebugDrawTestsVixen.Water.Physics.Tests
- BuoyancySystemTestsVixen.Water.Physics.Tests
- WaterSceneRunsTestsVixen.Editor.Assets.Tests