Two players, one world, and two simulations that never talk
Both marbles roll around the same scene graph. Neither simulation knows the other exists, except for the one frame they touch.
Two multiplayer modes landed together: Twin Explore, a tvOS split screen for two controllers, and Battle Royale, an Apple TV arena that up to three phones drop into over the local network. They share one decision.

TwinExploreLevel, drawn headlessly from the same
LevelData both simulations build their collision mesh from.
No props, no gates, no gravity zones — nothing either sim could
change and then disagree about.One scene, two simulations
A GameSim is one marble, one camera, one collision mesh. Widening it to carry
a second marble means every camera rule, ride and reset path grows a player
index — and the single-player game, which is the actual game, pays for
that forever.
So each player runs their own, and the rendering is what gets shared. One
renderer, one scene graph, one copy of the level geometry, two SCNViews
pointed at two camera nodes in the same scene. Player two’s marble is not
a copy kept in step in player one’s view; it is the same node, drawn
twice. Both sims build their own collision mesh from an identical level, so they
agree about the world without exchanging a byte.
The bill for that
That only holds while nothing in the world can change. Props, gates and gravity zones are per-simulation state — the instant one player topples a statue, the two sims disagree about a world they are supposedly sharing, and the renderer draws whichever one it happened to ask.
TwinExploreLevel therefore has none of them, and the constraint is a test
rather than a comment: “Level carries no state the two simulations could
disagree about.” Boing pads survive it because firing one is an event, not
state.
A quieter bill: both views share one set of materials, and the aerial-perspective band is derived from camera scale. Speed zoom is therefore off here. Leave it on and the distance fade pumps in player one’s half of the screen every time player two accelerates.
Battle Royale is the same shape with a network across it. The phone owns ordinary movement of its own marble and predicts its own camera, so packet timing never drives the view of the person holding it; the TV overrides that only for a collision or a respawn, each stamped with an epoch so a late packet cannot undo an impact that already happened.

The one contact where both sides move
The rest of the physics is sphere-against-world — the solver pushes a
marble out of triangles that never push back. Marble-against-marble is the
exception, and the one thing neither sim can work out alone, so it lives on its
own in MarbleContact: two states in, an outcome out, no level or gravity frame
in sight. Which makes it the most testable physics in the project, and it has
thirteen tests.
It is normal-only, no spin transfer. Not a shortcut: the marble’s roll is derived from its velocity rather than simulated, so there is no angular state for a tangential impulse to write to.
Both marbles take the full closing speed, not half each. They share one impulse, so a marble sitting still that gets hit at speed squashes exactly as hard as the one that hit it. Correct, and also the funnier read.
The separation is applied to the previous frame’s state as well as the current one. Render interpolation blends from the previous frame, so moving only the current state has the drawn marbles arrive at their separation a fraction late — sinking into each other on contact and popping apart after.
Costs
Contact runs once per rendered frame while the sim runs at 120Hz, so two marbles
closing flat out can overlap by up to 0.43 of their 1.0-unit diameter before
anything separates them. One frame of visible squish at a speed neither player
reaches often, and nothing can tunnel: that worst case is well under a diameter.
Making it exact means opening update into begin/substep/end so a caller could
interleave two sims — a larger change to the sim’s contract than the
effect is worth.
Neither mode is release content. The physics and the roster have tests; how it feels with four people shoving each other has been measured by nobody.