Access to core networking functionality can be obtained by using this.context.connection from a component. The built-in backend serveropen in new window requires users to be connected to a room.

Networking is currently based on websocketsopen in new window and sending either json strings (for infrequent updates) or flatbuffersopen in new window (for frequent updates).

Using Multiplayer

  • Enable Networking
    Add a SyncedRoom component.

  • Enable Desktop Viewer Sync
    Add a SyncedCamera component.

  • Enable XR Avatar Sync
    Add a WebXRSync component.

  • Enable Voice Chat
    Add a VoIP component.

  • Enable Screensharing
    Add a Screensharing component.

Core Components

  • SyncedRoom — handles networking connection and connection to a room.
    This can also be done by code using the networking api accessible from this.context.connection
  • SyncedTransform — handles synchronizing transforms
  • SyncedCamera — spawns a prefab for any user connected to the room which will follow their position
  • WebXRSync — handles synchronization for AR and VR users
  • VoIP — handles voice-over-IP audio connections, microphone access etc. between users
  • Networking — use to customize the server backend url

Manual Networking


Send a json message to all users in the same room:
this.context.connection.send(key:string, data: IModel | object | boolean | string | number | null)

Send a flatbuffer binary array to all users in the same room:


When sending an object containing a guid field it will saved in the persistant storage and automatically sent to users that connect later or come back later to the site (e.g. to restore state).
To delete state for a specific guid from the backend storage you can use delete-state as the key and provide an object with { guid: "guid_to_delete" }


Subscribe to json events / listen to events in the room using a specific key
this.context.connection.beginListen(key:string, callback:(data) => void)
Unsubscribe with stopListening

Subscribe to flatbuffer binary events
this.context.connection.beginListenBinrary(identifier:string, callback:(data : ByteBuffer) => void)
Unsubscribe with stopListenBinary

Auto Networking (experimental)

To automatically network fields in a component you can just decorate a field with a @syncField() decorator (note: you need to have experimentalDecorators: true in your tsconfig.json file for it to work)


import { Behaviour } from "@needle-tools/engine"
import { syncField } from "@needle-tools/engine/engine/engine_networking_auto";

export class AutoFieldSync extends Behaviour implements IPointerClickHandler {

    mySyncedValue?: number = 1;
    private myValueChanged() {
       console.log("My value changed", this.mySyncedValue);
    onPointerClick() {
       this.mySyncedValue = Math.random();

Flatbuffers for your own components

Built-in Networking on Glitch

When deploying your app to Glitch, we include a simple networking backend that is great for prototyping and small deployments (~15-20 people at the same time). You can later update to a bigger/better/stronger networking solution if required.


  • approx. 15-20 people maximum – afterwards the small default Glitch server instance becomes slow

How to upgrade to a stronger server

Needle Engine currently uses its own networking packageopen in new window hosted on npm. By default if not configured differently using the Networking component Needle Engine will connect to a server running on Glitch.

It can be added to your own fastiy or express server running on any server for example by adding the following code on your server after installing the package:

import networking from "@needle-tools/needle-tiny-networking-ws";
networking.startServerFastify(fastifyApp, { endpoint: "/socket" });

See the package's Readmeopen in new window for more information.

How to use your own networking implementation

🏗️ Under construction.

How to change from the default ICE/STUN servers used for VoIP

🏗️ Under construction.