lightyear_webrtc
Browser-only WebRTC transport for lightyear, built on web-sys.
Provides peer-to-peer data channels between two browser tabs using the standard WebRTC offer/answer flow. One peer acts as the host (creates the data channel) and the other as the client (receives it). Both sides are full WASM applications — there is no native server involved, except for STUN (and optional TURN) for NAT traversal.
Features
- Bevy plugin integration — drop in
WebRtcServerPlugin/WebRtcClientPluginand the connection lifecycle is managed through Bevy's ECS - lightyear_link compatible — connected peers get a
Linkcomponent for sending and receivingBytespayloads, fitting into lightyear's transport abstraction - Pluggable signaling — implement the
SignalingClienttrait to exchange SDP offers/answers however you want (WebSocket relay, Firebase, manual copy-paste, etc.) - Unreliable, unordered data channel — configured for low-latency game traffic (no retransmits, no ordering guarantees)
Cargo features
| Feature | Description |
|---|---|
client |
Enables WebRtcClientPlugin and WebRtcClientIo (guest/client role) |
server |
Enables WebRtcServerPlugin and WebRtcServerIo (host/server role) |
Neither feature is enabled by default. Enable what you need:
[]
= { = "0.26", = ["client", "server"] }
Quick start
use *;
use *;
use LinkStart;
// 1. Configure ICE servers
let ice_config = IceConfig ;
// 2. Provide a signaling implementation
let signaling = new;
// 3. Spawn the IO entity and trigger the connection
let entity = commands
.spawn
.id;
commands.trigger;
The client side is identical but uses WebRtcClientIo and WebRtcClientPlugin.
Once the WebRTC connection is established, the entity receives:
Linked— marks the connection as liveWebRtcChannels— exposesdata_tx/data_rxfor rawVec<u8>messagingLink— lightyear's transport abstraction withsend/recvbuffers
Signaling
Signaling is the mechanism used to exchange SDP offers and answers between peers before the WebRTC connection is established. This crate does not provide a signaling server — you bring your own by implementing SignalingClient:
Connection lifecycle
LinkStart triggered
-> Linking (async setup in progress)
-> Linked + WebRtcChannels (success)
-> Unlinked { reason } (failure)
Example: WebRTC Pong
The examples/webrtc_pong directory contains a minimal networked Pong game demonstrating the full connection flow with manual copy-paste signaling.
Building and running
Then open two browser tabs:
- Navigate to
http://localhost:8888/?host - Navigate to
http://localhost:8888/?client - Copy the OFFER from the host tab, paste it into the client tab
- Copy the ANSWER from the client tab, paste it back into the host tab
- Play Pong with arrow keys
The host is authoritative over ball physics and sends ball position to the client. Both peers send their paddle position to each other.
Requirements
- Target:
wasm32-unknown-unknown(browser only) - Rust: 1.88+
- Bevy: 0.18
License
Licensed under either of Apache License, Version 2.0 or MIT License at your option.