Skip to main content

Crate bevy_remote_wasm

Crate bevy_remote_wasm 

Source
Expand description

A plugin for the Bevy Remote Protocol that exposes remote methods to Wasm/JavaScript.

§Setup

  1. Add bevy_remote to your dependencies, and bevy_remote_wasm only for wasm targets.

    [dependencies]
    bevy = "0.18"
    bevy_remote = { version = "0.18", default-features = false }
    
    [target.'cfg(target_family = "wasm")'.dependencies]
    bevy_remote_wasm = "0.1"

    Don’t depend on bevy/bevy_remote (bevy = { version = "0.18", features = ["bevy_remote"] }) because it enables the default http transport, which does not compile on Wasm target (until this fix is merged and released).

    This is why it is recommended to depend on the separate crate bevy_remote with no default features (so bevy_remote/http is not enabled).

  2. Add RemotePlugin to your App, and add RemoteWasmPlugin only when compiling for Wasm.

    use bevy::prelude::*;
    use bevy_remote::RemotePlugin;
    
    let mut app = App::new();
    app.add_plugins((DefaultPlugins, RemotePlugin::default()));
    #[cfg(target_family = "wasm")]
    app.add_plugins(bevy_remote_wasm::RemoteWasmPlugin);
    app.run();
  3. Build for the wasm32-unknown-unknown target, then generate the JS bindings with wasm-bindgen directly (wasm-bindgen --target web --out-dir <output_dir> target/wasm32-unknown-unknown/debug/<crate_name>.wasm) or through a tool such as wasm-pack or Trunk.

  4. In JavaScript, load the generated JS module, call init(), then await getBridge():

    import init, { getBridge } from "/example.js";
    
    await init();
    const bridge = await getBridge();
    const response = await bridge.main["rpc.discover"]();
    console.log(response.info.version);

    The generated module path and init function depend on your build tool, but the initialization order does not: initialize the Wasm module first, then await the bridge.

    getBridge() may be called as soon as the JS module loads, but it resolves only after Bevy publishes the bridge during app startup, which, depending on your setup, may take some time.

    The wasm-bindgen output also includes TypeScript declarations for the root bridge (BrpBridge) and the default remote methods (BuiltInBrpBridge):

    import type { BuiltInBrpBridge } from "./example.js";
    
    const bridge = await getBridge() as BuiltInBrpBridge;
    const response = await bridge.main['world.query']({ data: { option: 'all' } });
    // Enjoy docs and autocompletion for built-in methods!
  5. Serve the generated HTML, JS, and .wasm files together from a web server or bundler that supports Wasm imports.

§Wasm API

The plugin builds a bridge object with app-scoped method maps based on the methods registered with RemotePlugin, more specifically through the RemoteMethods resource. Each time this resource is updated, the bridge is re-published with the new methods. The getBridge() function must be called again to get the updated bridge.

For Bevy 0.18, the bridge exposes only the main app. Method keys inside that namespace use the BRP method names directly, so call them with bracket notation such as bridge.main["world.query"] and bridge.main["world.list_components+watch"].

  • Instant methods (run once, return a result):
// Call the instant method with params but without callback.
// Returns the result wrapped in a Promise.
const result = await bridge.main['world.query']({ data: { option: 'all' } });
console.log(result);

// Call the instant method with params and a callback that will be called with the result.
// Returns `undefined` wrapped in a Promise.
await bridge.main['world.query']({ data: { option: 'all' } }, (result) => console.log(result));
  • Watching methods (stream results):
// Call the watching method with params and a callback that will be called on each result.
// Returns a closer function wrapped in a Promise.
const close = await bridge.main['world.list_components+watch']({ entity: 123 }, (result) => console.log(result));

// Stop the stream.
close();

Structs§

RemoteWasmPlugin
Add this plugin to your App to allow “remote” connections over Wasm to inspect and modify the World. It requires the RemotePlugin.