loomgui.com ↗

Loom has three pieces that talk to each other over a defined protocol.

The native plugin

The native plugin is a GPU-accelerated browser engine bundled inside the Unity package. It:

  • Renders your UI to a surface Unity composites over the game scene.
  • Forwards mouse and keyboard input from Unity into the UI.
  • Carries state, actions, and events between C# and the UI runtime.

You don’t write code against the plugin directly. Your C# code uses the bridge.

The bridge

You write a C# class and tag it with [Bridge]:

[Bridge]
public partial class GameBridge {
    [BridgeState] public int Score { get; set; }
    [BridgeAction] public void Pause() { /* ... */ }
    [BridgeEvent]  public Event<DamageEvent> Damaged { get; } = new();
}

A Roslyn source generator emits two things from this class:

  1. A runtime helper that serialises state and dispatches actions to the UI.
  2. A TypeScript .d.ts file that types the same surface for your UI code.

Your UI code uses useBridge() from @loomgui/bridge and gets fully typed bridge.state.score and bridge.actions.pause(), plus onEvent('damaged', …) for events.

See The bridge for the full data model.

The UI runtime

The UI is a normal Vite-built Solid app. @loomgui/vite-plugin handles the bridge connection for you. useBridge() returns a live, reactive bridge instance.

The same UI runs in two modes:

  • Connected. The bridge talks to a live Unity Editor or player. State pushes from the engine; actions call back.
  • Mock mode. No engine. Your bootBridge({ ... }) call provides mock actions and scenarios. The UI runs entirely in the browser. Used for fast iteration on visuals; see Mock mode.

Packaging

You install one Unity package. An Editor menu installs the npm packages into your UI app. See Sync UI Dependencies.