Networking
Access to core networking functionality can be obtained by using this.context.connection
from a component. The built-in backend server requires users to be connected to a room.
Networking is currently based on websockets and sending either json strings (for infrequent updates) or flatbuffers (for frequent updates).
Using Multiplayer
Enable Networking
Add aSyncedRoom
component.Enable Desktop Viewer Sync
Add aSyncedCamera
component.Enable XR Avatar Sync
Add aWebXRSync
component.Enable Voice Chat
Add aVoIP
component.Enable Screensharing
Add aScreensharing
component.
Core Components
SyncedRoom
— handles networking connection and connection to a room.
This can also be done by code using the networking api accessible fromthis.context.connection
SyncedTransform
— handles synchronizing transformsSyncedCamera
— spawns a prefab for any user connected to the room which will follow their positionWebXRSync
— handles synchronization for AR and VR usersVoIP
— handles voice-over-IP audio connections, microphone access etc. between usersNetworking
— use to customize the server backend url
Manual Networking
Sending
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:this.context.connect.sendBinary(arr:Uint8Array)
Persistence
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" }
Receiving
Subscribe to json events / listen to events in the room using a specific keythis.context.connection.beginListen(key:string, callback:(data) => void)
Unsubscribe with stopListening
Subscribe to flatbuffer binary eventsthis.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)
Example:
import { Behaviour } from "@needle-tools/engine"
import { syncField } from "@needle-tools/engine/engine/engine_networking_auto";
export class AutoFieldSync extends Behaviour implements IPointerClickHandler {
@syncField("myValueChanged")
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.
Limitations
- 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 package 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 Readme 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.