Laurens
New Member
Game Version
2026.9.7.5402Operating System
Windows 11What Happened
A physics bubble chooses its integration frame from its heaviest member, but the two rules that depend on that frame are applied per vehicle. When a bubble contains both a landed craft and an orbiting one, the orbiting vehicle is integrated in a rotating frame *without* the rotating-frame accelerations. It silently accrues roughly 0.42 m/s2 of error for as long as it stays in that bubble.As far as I can tell from the code, three individually reasonable decisions combine:
1. `PhysicsBubble` sorts `_vehicleStates` by descending mass and takes the bubble origin from the heaviest member.
2. `PhysicsStates.GetDesiredBubFrame` returns Ccf when that origin is inside the parent body's near-surface radius (~167 km on Earth). So a single landed craft makes the whole bubble rotating.
3. `PhysicsStates.ComputeDerivatives` applies -2w x v and -w x (w x r) inside `if (environment.InPhysicsRadius)` - a per-vehicle test that a vehicle at 1,380 km fails.
What Was Expected
If a vehicle is integrated in a rotating frame, it should get the fictitious terms. Omitting them isn't an approximation - it solves a different problem. I expected an orbiting upper stage to hold its orbit regardless of what else happens to be in its bubble, and specifically regardless of whether a heavy ground installation happens to be the bubble leader.WHY IT DOESN'T RECOVER ON ITS OWN
- `ComputeMergeStateCore` forces `IsRailsCoasting = false` for any multi-member bubble, so the bubble can't split back apart.
- `TryToPutOnRails` only restores rails through its `Origin.BubFrame.IsCci()` branch - in a rotating bubble there is no path back.
Once it starts, it persists for the rest of the flight.
EVIDENCE
Four upper stages in one world. For each, the spurious acceleration implied by its own observed drift, divided by its share of frames spent off rails:
| frames off rails | implied rate |
| 17% | 0.447 m/s2 |
| 24% | 0.436 m/s2 |
| 93% | 0.431 m/s2 |
| 100% | 0.428 m/s2 |
2w x v + w x (w x r) at 2.9 km/s predicts 0.42 m/s2. Four independent craft, a 6x spread in exposure, and 93% of the error is cross-track - which is what w x v looks like on a near-polar arc. That reads to me as the missing term rather than scatter, but I'd obviously defer to your own instrumentation.
WHY IT DOESN'T RECOVER ON ITS OWN
- `ComputeMergeStateCore` forces `IsRailsCoasting = false` for any multi-member bubble, so the bubble can't split back apart.
- `TryToPutOnRails` only restores rails through its `Origin.BubFrame.IsCci()` branch - in a rotating bubble there is no path back.
Once it starts, it persists for the rest of the flight.
WHY IT CASCADES
`PairFreeFlight.ComputeApproach` sets `nearContact` when centerDistance <= 5 * combinedRadius + 2, and that merges unconditionally. `ComputeMergeStateCore` then sets `EnvelopeRadius` to leader-to-furthest-member. So the moment one high vehicle joins a bubble that holds a landed craft, the envelope jumps to hundreds of km and its reach to five times that, and it swallows the rest of the world within a frame or two.
In our case 9 vehicles became a single 13-member bubble spanning 5 km to 1,387 km.
Reproduction Steps
Anything that puts a landed craft and an orbiting craft into one bubble will do it. Ours:
1. Place a ground installation at ~4.9 km elevation (ours was the heaviest object in the scene by a wide margin).
2. Launch to a near-polar orbit and leave the spent upper stage in orbit.
3. Let the upper stage pass over the ground installation while both are loaded.
4. Watch the upper stage's orbit decay/precess in a way that isn't explained by drag or any burn.
Frequency: roughly 1 in 30 passes for us, so it isn't 100% - but it's deterministic once it triggers, and it never recovers.
The tell, if you have a way to probe it: a coasting vehicle reporting a Ccf origin while the bubble leader is at low altitude and the vehicle itself is hundreds of km up.
Reproduction Rate
Roughly 1 in 30 passes for us, so it isn't 100% - but it's deterministic once it triggers, and it never recovers.
Last edited:
Upvote
2