lightyear_webrtc
Browser-only WebRTC transport for lightyear, built on web-sys.
https://github.com/user-attachments/assets/77cc416a-bc46-44e9-a073-7ffedd9ad3cf
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.
Disclaimer
This is mostly fun weekend project for me to learn about WebRTC, this is not really indended to be production ready transport solution. That said, if you find this useful or want to contribute, please open an issue or PR, I will try to respond when I have time.