Needle Engine
  • README
  • Code Of Conduct
  • HOW TO
  • documentation
    • SUMMARY
    • _backlog-mermaid
    • _backlog
    • _meta-test
    • Automatic Component Generation
    • Needle Core Components
    • How To Debug
    • Deployment and Optimization
    • embedding
    • Everywhere Actions
    • Example Projects ✨
    • Exporting Assets, Animations, Prefabs, Materials, Lightmaps...
    • Questions and Answers (FAQ) 💡
    • Feature Overview
    • This page has been moved: continue here
    • getting-started
    • Frameworks, Bundlers, HTML
    • index
    • Additional Modules
    • Networking
    • Needle Engine Project Structure
    • Samples Projects
    • Scripting Examples
    • Creating and using Components
    • Live
    • Live
    • About
    • Live
    • Live
    • Live
    • Live
    • Support, Community & AI
    • Technical Overview
    • Testimonials
    • Testing on local devices
    • Using Needle Engine directly from HTML
    • vision
    • VR & AR (WebXR)
    • blender
      • Needle Engine for Blender
    • cloud
      • Needle Cloud
    • custom-integrations
      • index
    • getting-started
      • Scripting Introduction for Unity Developers
      • Getting Started & Installation
      • Scripting in Needle Engine
    • reference
      • needle.config.json
      • <needle-engine> Configuration
      • @serializable and other decorators
    • three
      • index
    • unity
      • Editor Sync
      • Needle Engine for Unity
    • lang
      • de
        • 404
        • SUMMARY
        • Automatische Komponenten-Generierung
        • Needle-Kernkomponenten
        • Debugging
        • Bereitstellung und Optimierung
        • embedding
        • Everywhere Actions
        • Beispielprojekte ✨
        • Assets, Animationen, Prefabs, Materialien, Lightmaps exportieren...
        • Fragen und Antworten (FAQ) 💡
        • Funktionsübersicht
        • Diese Seite wurde verschoben: hier fortfahren
        • getting-started
        • Frameworks, Bundler, HTML
        • index
        • Zusätzliche Module
        • Netzwerkfunktionen
        • Needle Engine Projektstruktur
        • Beispielprojekte
        • Scripting Beispiele
        • Erstellen und Verwenden von Komponenten
        • Live
        • Live
        • Über
        • Live
        • Live
        • Live
        • Live
        • Support und Community
        • Technischer Überblick
        • Erfahrungsberichte
        • Testen auf lokalen Geräten
        • Needle Engine direkt aus HTML verwenden
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine für Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Einführung in das Scripting für Unity-Entwickler
          • Erste Schritte & Installation
          • Scripting in Needle Engine
        • reference
          • needle.config.json
          • <needle-engine> Konfiguration
          • @serializable und andere Decorators
        • three
          • index
        • unity
          • Editor Synchronisierung
          • Needle Engine für Unity
      • es
        • SUMMARY
        • Generación Automática de Componentes
        • Componentes principales de Needle
        • Cómo Depurar
        • Despliegue y optimización
        • embedding
        • Acciones Everywhere
        • Proyectos de Ejemplo ✨
        • Exportación de Assets, Animaciones, Prefabs, Materiales, Lightmaps...
        • Preguntas Frecuentes (FAQ) 💡
        • Resumen de Características
        • Esta página ha sido movida: continúe aquí
        • getting-started
        • Frameworks, Bundlers, HTML
        • index
        • Módulos Adicionales
        • Redes
        • Estructura de Proyecto de Needle Engine
        • Proyectos de ejemplo
        • Ejemplos de scripting
        • Crear y usar Components
        • En vivo
        • En Vivo
        • Acerca de
        • En vivo
        • En vivo
        • En vivo
        • En vivo
        • Soporte y Comunidad
        • Resumen técnico
        • Testimonios
        • Testing on local devices
        • Usando Needle Engine directamente desde HTML
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine para Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Introducción al Scripting para Desarrolladores de Unity
          • Primeros pasos e instalación
          • Scripting in Needle Engine
        • reference
          • needle.config.json
          • Configuración de <needle-engine>
          • @serializable y otros decoradores
        • three
          • index
        • unity
          • Editor Sync
          • Needle Engine para Unity
      • fr
        • SUMMARY
        • Génération automatique de composants
        • Composants principaux de Needle
        • Comment déboguer
        • Déploiement et Optimisation
        • embedding
        • Everywhere Actions
        • Exemples de Projets ✨
        • Exporter des Assets, des Animations, des Prefabs, des Matériaux, des Lightmaps...
        • Questions et Réponses (FAQ) 💡
        • Aperçu des fonctionnalités
        • Cette page a été déplacée : continuez ici
        • getting-started
        • Frameworks, Bundlers, HTML
        • index
        • Modules supplémentaires
        • Réseau
        • Structure du projet Needle Engine
        • Projets d'exemples
        • Exemples de Scripting
        • Créer et utiliser des Components
        • showcase-bike
        • En direct
        • À propos
        • En direct
        • Jouer
        • En direct
        • En direct
        • Support et Communauté
        • Vue d'ensemble technique
        • Témoignages
        • Tester sur les appareils locaux
        • Utiliser Needle Engine directement depuis HTML
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine pour Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Introduction au Scripting pour les Développeurs Unity
          • Premiers pas et installation
          • Scripting in Needle Engine
        • reference
          • needle.config.json
          • <needle-engine> Configuration
          • @serializable et autres décorateurs
        • three
          • index
        • unity
          • Synchronisation de l'Editor (Editor Sync)
          • Needle Engine pour Unity
      • hi
        • SUMMARY
        • कंपोनेंट का स्वतः जनरेशन
        • नीडल कोर कंपोनेंट्स
        • How To Debug
        • Deployment and Optimization
        • embedding
        • Everywhere Actions
        • उदाहरण प्रोजेक्ट ✨
        • एसेट, एनिमेशन, प्रीफैब, मटेरियल, लाइटमैप्स... को एक्सपोर्ट करना
        • प्रश्न और उत्तर (FAQ) 💡
        • सुविधा अवलोकन
        • यह पृष्ठ स्थानांतरित कर दिया गया है: यहां जारी रखें
        • getting-started
        • Frameworks, Bundlers, HTML
        • index
        • अतिरिक्त मॉड्यूल
        • नेटवर्किंग
        • Needle Engine प्रोजेक्ट स्ट्रक्चर
        • samples-and-modules
        • स्क्रिप्टिंग उदाहरण
        • कंपोनेंट बनाना और उपयोग करना
        • लाइव
        • लाइव
        • परिचय
        • लाइव
        • लाइव
        • लाइव
        • लाइव
        • समर्थन और समुदाय
        • तकनीकी अवलोकन
        • प्रशंसापत्र
        • Testing on local devices
        • HTML से सीधे Needle Engine का उपयोग करना
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine for Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Unity डेवलपर्स के लिए स्क्रिप्टिंग परिचय
          • आरंभ करना और इंस्टॉलेशन
          • Needle Engine में स्क्रिप्टिंग
        • reference
          • needle.config.json
          • <needle-engine> कॉन्फ़िगरेशन
          • @serializable and other decorators
        • three
          • index
        • unity
          • Editor Sync
          • Unity के लिए Needle Engine
      • ja
        • SUMMARY
        • 自動コンポーネント生成
        • Needleコアコンポーネント
        • デバッグの方法
        • デプロイと最適化
        • embedding
        • Everywhere Actions
        • サンプルプロジェクト ✨
        • アセット、アニメーション、Prefab、マテリアル、ライトマップなどのエクスポート
        • よくある質問(FAQ)💡
        • 機能概要
        • このページは移動しました: こちらからどうぞ
        • getting-started
        • フレームワーク、バンドラー、HTML
        • index
        • 追加モジュール
        • ネットワーキング
        • Needle Engineプロジェクトの構造
        • サンプルプロジェクト
        • スクリプティング例
        • Creating and using Components
        • ライブ
        • showcase-castle
        • 概要
        • ライブ
        • ライブ
        • ライブ
        • ライブ
        • サポートとコミュニティ
        • 技術概要
        • お客様の声
        • ローカルデバイスでのテスト
        • HTMLからNeedle Engineを直接使用する
        • vision
        • VR & AR (WebXR)
        • blender
          • Blender 用 Needle Engine
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Scripting Introduction for Unity Developers
          • はじめに & インストール
          • Needle Engineでのスクリプティング
        • reference
          • needle.config.json
          • <needle-engine> 設定
          • @serializable およびその他のデコレーター
        • three
          • index
        • unity
          • Editor Sync
          • Unity用Needle Engine
      • pt
        • SUMMARY
        • Automatic Component Generation
        • Componentes Principais do Needle
        • Como Depurar
        • Implementação e Otimização
        • embedding
        • Everywhere Actions
        • Projetos de Exemplo ✨
        • Exportar Recursos, Animações, Prefabs, Materiais, Lightmaps...
        • Perguntas e Respostas (FAQ) 💡
        • Visão Geral dos Recursos
        • Esta página foi movida: continue aqui
        • getting-started
        • Frameworks, Bundlers, HTML
        • index
        • Módulos Adicionais
        • Redes
        • Estrutura do Projeto Needle Engine
        • Projetos de Exemplo
        • Exemplos de Scripting
        • Criar e usar Componentes
        • Ao Vivo
        • Ao Vivo
        • Sobre
        • Ao Vivo
        • Ao Vivo
        • Ao Vivo
        • Ao Vivo
        • Suporte e Comunidade
        • Visão Geral Técnica
        • Depoimentos
        • Testar em dispositivos locais
        • vanilla-js
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine para Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Introdução à Scripting para Developers Unity
          • Começar e Instalação
          • Scripting no Needle Engine
        • reference
          • needle.config.json
          • needle-engine-attributes
          • @serializable e outros decorators
        • three
          • index
        • unity
          • Sincronização do Editor
          • Needle Engine para Unity
      • vn
        • 404
        • SUMMARY
        • Automatic Component Generation
        • Các Component Cốt lõi của Needle
        • Cách gỡ lỗi
        • Triển khai và Tối ưu hóa
        • embedding
        • Hành động ở mọi nơi (Everywhere Actions)
        • Các Dự Án Ví Dụ ✨
        • Xuất Tài sản, Hoạt ảnh, Prefab, Vật liệu, Lightmap...
        • Câu hỏi thường gặp (FAQ) 💡
        • Tổng quan tính năng
        • Trang này đã được di chuyển: tiếp tục tại đây
        • getting-started
        • Frameworks, Bundlers, HTML
        • index
        • Các Module Bổ Sung
        • Kết nối mạng
        • Cấu trúc dự án Needle Engine
        • samples-and-modules
        • Ví dụ về Scripting
        • Tạo và sử dụng Component
        • Trực tiếp
        • Trực tiếp
        • Giới thiệu
        • Trực tiếp
        • Chơi thử
        • Trực tiếp
        • Demo trực tiếp
        • Hỗ trợ và Cộng đồng
        • Tổng quan kỹ thuật
        • Lời chứng thực
        • Testing on local devices
        • Sử dụng Needle Engine trực tiếp từ HTML
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine cho Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Giới thiệu về Scripting cho các nhà phát triển Unity
          • Getting Started & Installation
          • Scripting trong Needle Engine
        • reference
          • needle.config.json
          • Cấu hình <needle-engine>
          • @serializable và các decorator khác
        • three
          • index
        • unity
          • Editor Sync
          • Needle Engine cho Unity
      • zh
        • SUMMARY
        • 自动生成组件
        • Needle 核心组件
        • 如何调试
        • 部署与优化
        • embedding
        • Everywhere Actions
        • 示例项目 ✨
        • 导出资源、动画、预制体、材质、光照贴图...
        • 常见问题 (FAQ) 💡
        • 功能概览
        • 此页面已移动:请在此处继续
        • getting-started
        • 框架、打包器、HTML
        • index
        • 附加模块
        • 网络
        • Needle Engine 项目结构
        • 示例项目
        • Scripting Examples
        • Creating and using Components
        • 实时示例
        • 实时
        • 关于
        • 实时演示
        • 在线试玩
        • 实时演示
        • 现场演示
        • 支持与社区
        • 技术概述
        • 用户评价
        • Testing on local devices
        • 使用 Needle Engine 直接从 HTML
        • vision
        • VR & AR (WebXR)
        • blender
          • Needle Engine for Blender
        • cloud
          • Needle Cloud
        • custom-integrations
          • index
        • getting-started
          • Scripting Introduction for Unity Developers
          • 入门与安装
          • 在 Needle Engine 中编写脚本
        • reference
          • needle.config.json
          • <needle-engine> 配置
          • @serializable and other decorators
        • three
          • index
        • unity
          • 编辑器同步
          • Unity 版 Needle Engine
Powered by GitBook
On this page
  • Networking Concepts
  • Rooms and State
  • Ownership
  • Enable Networking for your project
  • Built-In Components with Networking Support
  • Automatic Networking for custom Components
  • Creating and destroying objects
  • Manual Networking
  • Sending Messages
  • Receiving Messages
  • Controlling message persistence
  • Using debug flags to understand network messages
  • Networking Lifecycle Events
  • Using Needle Networking Servers
  • Hosting your own Networking Server
  • Configuration
  • Local Networking Server
  • Advanced: Customizing WebRTC settings for peer.js
  • Advanced: Server and Client Message Formats
  • Built-in Room Events
  • Built-In Utility Events
  • Built-In Ownership Events
  • Built-In Flatbuffer Schemas
  • Advanced: Binary Messages in the Flatbuffer format
  • Summary
Edit on GitHub
  1. documentation

Networking

PreviousAdditional ModulesNextNeedle Engine Project Structure

Last updated 1 month ago

Needle Engine includes a full networking solution for multiplayer experiences. A shared world state, voice chat, session persistence, and more can be achieved with our networking components and APIs. You can network your own components with a choice of automatic or manual networking.

Networking in Needle Engine is based on . Automatic networking uses JSON data for ease of use. For complex usecases and high-performance requirements, we use .

Access to core networking functionality can be obtained by using this.context.connection from a component. The default backend server connects users to rooms. Users in the same room will share state and receive messages from each other.

Networking Concepts

Rooms and State

At the heart of networking in Needle Engine is the concept of synchronized rooms. Each room has an ID, and users connect to a room by providing this ID. Rooms are stored on a server, and users can join and leave rooms at any time. When a user joins a room, they receive the current state of the room, apply that current state to their scene, and then listen for changes to the room state. When a user leaves a room, they stop listening for changes to the room state.

Room state is stored as JSON data on the server, so all changes are persistent. This means that room state is not only useful for networking, but also for persisting actions of a single user.

Needle can provide view-only IDs for rooms. When accessing a room with a view-only ID, the user will not be able to interact with the room, but will be able to see the current state and get live updates. This is useful for presentations or demonstrations.

Ownership

Objects in a room can be owned by a user. This means that only the owner of an object can change its state. By default, objects have no owner. Components like DragControls will request ownership of an object before actually moving it. In custom components, you can control how ownership is handled. There may be no ownership required, ownership may be allowed to be transferred to another user automatically, or ownership may be transferred only by a specific action.

When a user leaves a room, objects owned by that user will either be deleted or have ownership reset, depending on how the object was created.

Enable Networking for your project

  1. Add a SyncedRoom component to your scene. By default, this will use networking infrastructure provided by Needle.

  2. Add a SyncedTransform component to a object whose movement you want to synchronize across the network.

  3. Add a DragControls component to the same object.

  4. Run the project. In the browser, click on "Join Room" and copy the URL.

  5. Open a new browser window and paste the URL. You should now see the same object in both windows. Try dragging the object in one window and see it move in the other window.

The DragControls component, like many other Needle components, has built-in networking support. Ownership will be transferred to whoever starts dragging the object.

Built-In Components with Networking Support

Component
Description

SyncedRoom

Handles networking connection and connection to a room.

SyncedTransform

Handles synchronizing transforms.

SyncedCamera

Spawns a prefab for any user connected to the room which will follow their position.

VoIP

Handles voice-over-IP audio connections, microphone access etc. between users.

ScreenCapture

Handles screensharing via web APIs.

Networking

Use to customize the server backend URL. Also allows setting a local server for development.

DragControls

Handles dragging objects. Ownership will automatically be passed to the last user dragging an object.

Duplicatable

Handles duplicating objects. Duplicated objects are instantiated for everyone in the room.

Deletable

Handles deleting objects. Deletions are synchronized across the network.

DeleteBox

Handles deleting objects that have a "Deletable" component when they are dragged into a box volume.

PlayerSync

Powerful component that instantiates a specific object for each connected player.

PlayerState

Add this component to objects that are assigned to PlayerSync.

PlayerColor

Simple component for player-specific colors. Each user gets assigned a random color upon joining a room. This component assigns that color to the object's main material.

WebXR

Handles synchronizing user avatars (hands and heads).

Automatic Networking for custom Components

Fields in your own components can be networked very easily. Changes to the field will automatically be detected and sent to all users in the room. The changes are also persisted as part of the Room State, so users that join the room later will receive the current state of the field as well, ensuring everyone sees the same data.

To automatically network a field in a component, decorate it with the @syncField() decorator:

::::code-group :::code-group-item Sync a number

import { Behaviour, syncField, IPointerClickHandler } from "@needle-tools/engine"

export class SyncedNumber extends Behaviour implements IPointerClickHandler {

    // Use `@syncField` to automatically network a field. 
    // You can optionally assign a method or method name to be called when the value changes.
    @syncField("myValueChanged")
    mySyncedValue?: number = 1;
    
    private myValueChanged() {
       console.log("My value changed", this.mySyncedValue);
    }
    
    onPointerClick() {
       this.mySyncedValue = Math.random();
    }
}

::: :::code-group-item Sync an object's color

::: ::::

Note that syncField has an optional parameter to specify a method that should be called when the value changes. This method should be defined in the same class.

::: tip Custom Project Setup If you're using a custom project setup, you need to have experimentalDecorators: true in your tsconfig.json file for syncField decorators to work. Projects created with Needle Starters have this enabled by default. :::

Creating and destroying objects

Often, you want to create and destroy objects at runtime, and of course these changes should be synchronized across the network.

The PlayerSync component simplifies this process by automatically instantiating a specific object for each connected player. When a player leaves the room, the object is destroyed for all users.

Additionally, Needle Engine provides two high-level methods:

🏗️ Code Samples Under Construction

Manual Networking

Needle Engine also provides a low-level API for sending and receiving messages. We call this "manual networking". The principles are the same, but you're in full control for sending and receiving messages and how to handle them.

Sending Messages

Send a message to all users in the same room:

this.context.connection.send(key: string, data: IModel | object | boolean | string | number | null);

Receiving Messages

You can subscribe to events in the room using a specific key. Typically, you want to match this with unsubscribing:

  • subscribe in onEnable and unsubscribe in onDisable With this approach, no messages will be received while the object is disabled.

  • or subscribe in start and unsubscribe in onDestroy With this approach, messages will still be received while the object is disabled.

this.context.connection.beginListen(key:string, callback:(data) => void)

Unsubscribe from events:

this.context.connection.stopListen(key:string)

Controlling message persistence

When sending network messages, the low-level API allows you to decide whether that message should be persistet (saved in the room state) or not (only sent to users currently in the room). To persist a message, make sure it has a guid field. This field is typically used to apply the message data to a specific object, by providing that object's guid. If you want target a specific object (and thus, include a guid field) but want the data to not be persisted, set the dontSave field to true in your message.

All persistent messages are saved in the room state and will be sent to users that connect at a later point. Non-persistent messages are only sent to users currently in the room, which is useful for effects (like playing a sound effect) that don't make sense to play for users that are currently not in the room. Optionally, you can include a deleteOnDisconnect field in your message to delete this particular message when the user disconnects.

// This message will be sent to all users currently in the room,
// AND to users that join the room later.
this.context.connection.send("my-message", { guid: this.guid, myData: "myValue" });

// This message will be sent to all users currently in the room,
// but NOT be sent to users that join the room later.
this.context.connection.send("my-message", { guid: this.guid, myData: "myValue", dontSave: true });

// This message will be sent to all users currently in the room,
// but NOT be sent to users that join the room later.
this.context.connection.send("my-message", { myData: "myValue" });

// This message will be sent to all users currently in the room,
// AND to users that join the room later,
// but will be deleted from the room state when the user disconnects.
this.context.connection.send("my-message", { guid: this.guid, myData: "myValue", deleteOnDisconnect: true });

To delete state for a specific guid from the backend storage, set the message key to delete-state and target a specific object with its guid: { guid: "guid_to_delete" } .

this.context.connection.send("delete-state", { guid: "guid_to_delete" });

Using debug flags to understand network messages

There are several debug flags that can be used to dive deeper into network messages. These can be appended the the page URL, like https://localhost:3000/?debugnet.

Flag
Description

?debugnet

Log all incoming and outgoing network messages to the console

?debugowner

Log all ownership requests and changes to the console

?debugnetbin

Log additional information for incoming and outgoing binary messages

Networking Lifecycle Events

The following events are available to listen to in your components. They describe common network events that you might want to react to in your components, like yourself or another user joining or leaving a room.

// Listen to the event when *you* have joined a networked room
this.context.beginListen(RoomEvents.JoinedRoom, ({room, viewId, allowEditing, inRoom}) => { ... });

// Listen to the event when *you* have left a networked room
this.context.beginListen(RoomEvents.LeftRoom, ({room}) => { ... });

// Listen to the event when *another user* has joined your networked room
this.context.beginListen(RoomEvents.UserJoinedRoom, ({userId}) => { ... });

// Listen to the event when *another user* has left your networked room
this.context.beginListen(RoomEvents.UserLeftRoom, ({userId}) => { ... });

// This event is received after all current room state has been sent to the client
this.context.beginListen(RoomEvents.RoomStateSent, () => { ... });

Using Needle Networking Servers

By default, networked Needle scenes connect to cloud infrastructure managed and provided by Needle. There is no additional setup needed, and currently no additional cost for using this service.

Typically, this will work fine for around 15-20 users in the same room. Once your project matures, you can upgrade to a bigger/better/stronger networking solution, by hosting your own networking server.

Hosting your own Networking Server

You might want to host your own networking server for larger deployments or to have more control over the networking infrastructure and implementation.

The default Glitch server instance is small and can only handle a limited amount of users. If you expect more than 15-20 people to be in your scene at the same time, you should consider hosting your networking server elsewhere (like on Google Cloud or AWS). :::

::::code-group :::code-group-item Fastify

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

::: :::code-group-item Express

import networking from "@needle-tools/needle-networking";
networking.startServerExpress(expressApp, { endpoint: "/socket" });

::: :::code-group-item Custom Integration

import { init, onConnection } from "@needle-tools/networking";

// Add your framework-specific websocket implementation here. 
// You can view the fastify and express implementations in server.js for reference.
class WebsocketConnector {
    constructor(frameworkWebsocket) {
        // Your implementation.
    }
    on(event, callback) {
        // Your implementation. When receiving a message in the websocket connection, call the callback.
        // 'event' can be 'message' or 'close'.
    }
    send(key, value) {
        // Your implementation. Pass the message along to the websocket connection.
    }
}
const options = { endpoint: "/socket" };
init(options);
yourFramework.createWebsocketRoute(options.endpoint, frameworkWebsocket => {
    onConnection(new WebsocketConnector(frameworkWebsocket));
});

::: ::::

Configuration

The following options are available:

Option
Description

options.endpoint string

Optional. Relative server endpoint. For example, /socket will start the websocket endpoint on yourserver/socket. Defaults to /.

options.maxUsers number

Maximum number of concurrent users on a server. Defaults to 50.

options.defaultUserTimeout number

Time in seconds after which a user is considered disconnected. Defaults to 30.

process.env.VIEW_ONLY_SALT string

Salt value used for generating view-only room IDs from regular room IDs. Defaults to a predefined salt value.

process.env.NEEDLE_NETWORKING_S3_* string

Enable S3 storage. See below for the full list of environment variables you need to set for this. When not set, the default storage is used (JSON files on disk).

The networking server will automatically manage connecting and disconnecting users, receiving and sending messages, and persisting room state.

::: tip Different server locations for local and hosted development If you're working on custom networking code, you may want to use different server locations for local development and the hosted app. You can set individual server URLs in the Networking component:

State Storage

Network state is by default stored to disk on the server as JSON files in the /.data directory. Each room has its own file, and the state is sent to connecting clients when they join a room.

Optionally, the networking state can be stored with an S3 compatible storage provider. Use the following environment variables to enable S3 storage:

NEEDLE_NETWORKING_S3_ENDPOINT=
NEEDLE_NETWORKING_S3_REGION=
NEEDLE_NETWORKING_S3_BUCKET=
NEEDLE_NETWORKING_S3_ACCESS_KEY_ID=
NEEDLE_NETWORKING_S3_ACCESS_KEY=
NEEDLE_NETWORKING_S3_PREFIX= # all state saved in the bucket will be prefixed with this string. This can be a path e.g. `my_state/` or a unique id `server_123_`

Local Networking Server

For testing and development purposes, you can run the Needle Engine networking package on a local server. We have prepared a repository that is set up to host the websocket package and to make that easy for you.

  1. Follow the instructions in the README to set up the server. The server will run on wss://localhost:9001/socket by default.

  2. Add the Networking component to your scene.

  3. Paste the local server address into the Localhost field on the Networking component.

Advanced: Customizing WebRTC settings for peer.js

Needle Engine uses reasonable defaults for peerjs. If you want to modify those defaults, you can call

setPeerOptions(opts: PeerjsOptions);

with your custom settings. This can be used to modify the hosting provider for ICE/STUN/TURN servers, for example when you use your own WebRTC servers.

Advanced: Server and Client Message Formats

::: warning For informational purposes. Use the APIs provided by Needle Engine instead. Typically, you do not need to interact with these message formats directly, as the low-level networking API already handles parsing messages and giving you the correct types. The information here is provided for advanced users who want to understand the underlying message formats or implement their own networking solutions. :::

Messages are sent in JSON format. They always have a key field that describes the type of message, and a data field that contains the message payload. The data field can be any JSON-serializable object.

Built-in Room Events

::::code-group :::code-group-item Join

// Sent to the server to attempt joining a room.
{
    "key": "join-room",
    "data": {
        "room": string,
        "viewOnly": boolean,
    }
}

::: :::code-group-item Leave

// Sent to the server to leave a room.
{
    "key": "leave-room",
    "data": {
        "room": string
    }
}

::: :::code-group-item JoinedRoom

// Sent to the client when the local user has joined a room.
// Type: JoinedRoomResponse
{
    "key": "joined-room",
    "room": string,
    "viewId": string,
    "allowEditing": boolean,
    "inRoom": string[] // connection IDs
}

::: :::code-group-item LeftRoom

// Sent to the client when the local user has left a room.
// Type: LeftRoomResponse
{
    "key": "left-room",
    "room": string
}

::: :::code-group-item UserJoinedRoom

// Sent to the client when any user has joined a room.
// Type: UserJoinedOrLeftRoomModel
{
    "key": "user-joined-room",
    "data": {
        "userId": string // connection ID
    }
}

::: :::code-group-item UserLeftRoom

// Sent to the client when any user has left a room.
// Type: UserJoinedOrLeftRoomModel
{
    "key": "user-left-room",
    "data": {
        "userId": string // connection ID
    }
}

::: :::code-group-item RoomStateSent

// Sent to the client after the complete room state has been sent.
{
    "key": "room-state-sent",
    "room": string // room name 
}

::: ::::

Built-In Utility Events

::::code-group :::code-group-item ConnectionInfo

// Sent to the client when the connection is established.
{
    "key": "connection-start-info",
    "data": {
        "id": string // connection ID
    }
}

::: :::code-group-item syncInstantiate

// Used by the syncInstantiate() API to create a new instance of an asset.
// Type: NewInstanceModel
{
    "key": "new-instance-created",
    "data": {
        "guid": string,
        "originalGuid": string,
        "seed": number | undefined,
        "visible": boolean | undefined,
        "dontSave": boolean | undefined,

        "parent": string | undefined,
        "position": { x: number, y: number, z: number } | undefined,
        "rotation": { x: number, y: number, z: number, w: number } | undefined,
        "scale": { x: number, y: number, z: number } | undefined,

        "deleteStateOnDisconnect": boolean | undefined
    }

::: :::code-group-item syncDestroy

// Used by the syncDestroy() API to destroy an instance of an asset.
// Type: DestroyInstanceModel
{
    "key": "instance-destroyed",
    "data": {
        "guid": string,
        "dontSave": boolean | undefined
    }
}

::: :::code-group-item Ping

// Sent to the server every few seconds to keep the connection alive.
{
    "key": "ping",
    "data": {}
}

::: :::code-group-item Pong

// Sent by the server in response to a ping.
{
    "key": "pong",
    "data": {}
}

::: :::code-group-item DeleteState

// Sent to the server to delete state for a specific guid.
{
    "key": "delete-state",
    "data": {
        "guid": <string>
    }
}

::: :::code-group-item DeleteAllState

// Sent to the server to delete ALL current room state.
{
    "key": "delete-all-state",
    "data": {}
}

::::

Built-In Ownership Events

::::code-group :::code-group-item OwnershipRequest

{
    "key": 
      "request-has-owner" | 
      "request-ownership" | 
      "remove-ownership",
    "data": {
        "guid": string
    }
}

::: :::code-group-item OwnershipResponse // Type: OwnershipResponse

{
    "key": 
      "response-has-owner",
    "data": {
        "guid": string,
        "value": boolean
    }
}

::: ::: code-group-item OwnershipBroadcastResponse

{
    "key": 
      "gained-ownership" | 
      "lost-ownership" | 
      "gained-ownership-broadcast" | 
      "lost-ownership-broadcast",
    "data": {
        "guid": string,
        "owner": string
    }
}

::: ::::

Built-In Flatbuffer Schemas

Flatbuffer messages are sent directly as binary messages.

::::code-group :::code-group-item SyncedTransform ('STRS')

<!-- SAMPLE node_modules/@needle-tools/engine/src/engine-schemes/transforms.fbs -->

::: :::code-group-item SyncedCamera ('SCAM')

<!-- SAMPLE node_modules/@needle-tools/engine/src/engine-schemes/syncedCamera.fbs -->

::: :::code-group-item Vec2|3|4

<!-- SAMPLE node_modules/@needle-tools/engine/src/engine-schemes/vec.fbs -->

::: ::::

Advanced: Binary Messages in the Flatbuffer format

JSON messages are easy to use and understand, but are typically larger in memory and bandwidth. For large amounts of data, or when sending fast updates, binary messages are faster and more efficient. You can use Flatbuffers messages in Needle Engine for cases where that is required. Using Flatbuffers requires additional setup steps like defining and compiling a message schema, and is harder to debug since you're dealing with binary messages.

Note that when sending and receiving flatbuffer messages, there is no key field – the message type is part of the Flatbuffer schema. What you send and receive over the Websocket connection is a single binary buffer.

Send a binary message to all users in the same room:

this.context.connection.sendBinary(byteArray: Uint8Array);

Subscribe to binary messages in Flatbuffer format:

this.context.connection.beginListenBinary(identifier:string, callback:(data : ByteBuffer) => void);

Unsubscribe from binary messages:

this.context.connection.stopListenBinary(identifier:string);

Flatbuffers Sample Code

Before you can send and receive Flatbuffer messages, you need to define a schema and compile it to TypeScript. Then, register the schema with the networking system and use the generated schema methods to create and parse messages.

::::code-group :::code-group-item Register a schema

// Register a new Flatbuffer schema with the networking system
import { registerBinaryType } from '@needle-tools/engine';
import { MyDataModel } from 'my-data-model.js';

const MySchemaIdentifier = "MYSC";

registerBinaryType(MySchemaIdentifier, MyDataModel.getRootAsSyncedTransformModel);

::: :::code-group-item Send Messages

// Prepare data for sending by creating a Flatbuffer message:
import { MyDataModel } from 'my-data-model.js';

const MySchemaIdentifier = "MYSC";
const builder = new flatbuffers.Builder();

// Construct a Flatbuffer message
function createMyCustomModel(somePayload: string): Uint8Array {
    builder.clear();
    MyDataModel.startMyDataModel(builder);    
    const guidObj = builder.createString(guid);
    MyDataModel.addSomePayload(builder, guidObj);
    const res = MyDataModel.endMyDataModel(builder);
    builder.finish(res, MySchemaIdentifier);
    return builder.asUint8Array();
}

// Send the data
function sendData() {
    const data = createMyCustomModel("your-payload", this, true);
    this.context.connection.sendBinary(data);
}

::: :::code-group-item Receive Messages

// Subscribe to receive this specific message type:
import { MyDataModel } from 'my-data-model.js';

const MySchemaIdentifier = "MYSC";

this.context.connection.beginListenBinary(MySchemaIdentifier, (data) => {
    const model = MyDataModel.getRootAsMyDataModel(data);
    console.log("Received binary message", model, model.somePayload());
});

::: ::::

::: tip Custom Flatbuffer messages and persistence Currently, custom binary messages can't be persisted on the networking server. Modify the networking server and add your custom flatbuffer schemas to ensure the guid property can be processed. :::

Summary

Needle Engine makes the complex topic of networking approachable and easy to use. You can get started with automatic networking for your components with just a few lines of code, and you can dive deeper into manual networking when you need more control.

to duplicate objects across the network.

to destroy objects across the network.

Our networking server is available on NPM as node.js package. The package contains pre-configured integrations for the popular web frameworks and , and can be integrated into other Node.js server frameworks as well.

::: tip For quick experiments: Remix on Glitch You can remix a simple networking server running on Glitch from this page: by clicking the button in the bottom right corner.

::: tip Example on Glitch.com See the code on for an example of how to integrate Needle Networking with an Express server. :::

Custom networking servers can be deployed anywhere, for example on Google Cloud. For further instructions please refer to this repository:

:::

Download the local server sample from

Needle Engine Screencapture (Screensharing) and VoIP (Voice communication) components use for networking audio and video. Peer.js uses WebRTC under the hood.

Websockets
Flatbuffers
syncInstantiate()
syncDestroy()
See all Room Events in the API docs
See all Ownership Events in the API docs
See all Connection Events in the API docs
own networking package
Fastify
Express
needle-networking.glitch.me
glitch.com/edit/#!/needle-networking
Local Needle Networking Server
github.com/needle-tools/networking-local
peer.js
Generating a schema
Using the schema compiler
Flatbuffers in Typescript
Built-in Flatbuffer schemas in Needle Engine