Skip to content

Mock mode

Mock mode lets you run the UI in a normal browser, without Unity, without the native plugin, without a WebSocket. Your bootBridge({ ... }) call provides mock implementations of every action plus a set of named scenarios you can trigger from a dev-tools panel.

Why mock?

  • Speed. A Vite dev server reload is <100 ms. A Unity domain reload is 4–20 s. Iterating on layout, animation, and styling against the engine is painful; iterating in mock is instant.
  • Determinism. Scenarios let you trigger specific UI states reproducibly: “Boot Progress 0.5”, “Take Damage”, “Open Pause Menu”. No need to play through the game to hit a particular screen.
  • Designer-friendly. A non-Unity dev can run the UI app standalone and see the full flow.

Setting up mock mode

Your UI’s index.tsx calls bootBridge with two optional fields beyond the initial state:

const bridge = bootBridge({
initial: {
currentScreen: 'Splash',
bootProgress: 0,
counterValue: 0,
},
// run when the UI calls bridge.actions.foo() in mock mode
mockActions: {
dismissSplash: () => { bridge.state.currentScreen = 'Main' },
increment: () => { bridge.state.counterValue += 1 },
// ...
},
// trigger from the dev-tools panel
mockScenarios: {
'Goto Splash': ({ state }) => {
state.currentScreen = 'Splash'
state.bootProgress = 0
},
'Take Damage': ({ state, fire }) => {
state.hudHealth = Math.max(0, state.hudHealth - 25)
fire('damaged', { amount: 25 })
},
},
})

When the bridge boots without a loomWsUrl query parameter (i.e. you ran npm run dev standalone), it enters mock mode. The actions provided in mockActions run instead of being sent to the engine; the scenarios appear in the floating dev-tools panel.

When connected

When bootBridge sees a loomWsUrl=... query string (set automatically when running under Unity), it connects to that URL and ignores mockActions. mockScenarios are also ignored in connected mode — the engine is the source of state truth.

A tip

Keep the action surface in mock mode behaviorally identical to the engine side. The point is that the same Solid code runs against both. If your mock action does something wildly different from what the engine does, your mock-mode iteration loop is lying.