Netzwerkfunktionen
Last updated
Last updated
Needle Engine enthält eine vollständige Netzwerklösung für Multiplayer-Erlebnisse. Ein geteilter Weltzustand, Sprachchat, Sitzungspersistenz und mehr können mit unseren Netzwerkkomponenten und APIs erreicht werden. Sie können Ihre eigenen Komponenten vernetzen, wahlweise automatisch oder manuell.
Die Vernetzung in Needle Engine basiert auf . Die automatische Vernetzung verwendet JSON-Daten für einfache Handhabung. Für komplexe Anwendungsfälle und hohe Leistungsanforderungen nutzen wir .
Der Zugriff auf die Kernfunktionen des Netzwerks kann über this.context.connection
aus einer Komponente erfolgen. Der standardmäßige Backend-Server verbindet Benutzer mit Räumen. Benutzer im selben Raum teilen den Zustand und empfangen Nachrichten voneinander.
Im Mittelpunkt der Vernetzung in Needle Engine steht das Konzept der synchronisierten Räume. Jeder Raum hat eine ID, und Benutzer verbinden sich mit einem Raum, indem sie diese ID angeben. Räume werden auf einem Server gespeichert, und Benutzer können Räumen jederzeit beitreten und sie verlassen. Wenn ein Benutzer einem Raum beitritt, erhält er den aktuellen Zustand des Raums, wendet diesen aktuellen Zustand auf seine Szene an und wartet dann auf Änderungen des Raumzustands. Wenn ein Benutzer einen Raum verlässt, wartet er nicht mehr auf Änderungen des Raumzustands.
Der Raumzustand wird als JSON-Daten auf dem Server gespeichert, sodass alle Änderungen persistent sind. Das bedeutet, dass der Raumzustand nicht nur für die Vernetzung nützlich ist, sondern auch für die Persistenz der Aktionen eines einzelnen Benutzers.
Needle kann Nur-Ansicht-IDs für Räume bereitstellen. Beim Zugriff auf einen Raum mit einer Nur-Ansicht-ID kann der Benutzer nicht mit dem Raum interagieren, aber den aktuellen Zustand sehen und Live-Updates erhalten. Dies ist nützlich für Präsentationen oder Demonstrationen.
Objekte in einem Raum können von einem Benutzer besessen werden. Das bedeutet, dass nur der Besitzer eines Objekts dessen Zustand ändern kann.
Standardmäßig haben Objekte keinen Besitzer.
Komponenten wie DragControls
fordern den Besitz eines Objekts an, bevor sie es tatsächlich verschieben.
In benutzerdefinierten Komponenten können Sie steuern, wie der Besitz gehandhabt wird.
Es kann sein, dass keine Besitzrechte erforderlich sind, Besitzrechte automatisch an einen anderen Benutzer übertragen werden dürfen oder Besitzrechte nur durch eine bestimmte Aktion übertragen werden.
Wenn ein Benutzer einen Raum verlässt, werden Objekte, die diesem Benutzer gehören, entweder gelöscht oder die Besitzrechte werden zurückgesetzt, je nachdem, wie das Objekt erstellt wurde.
Fügen Sie Ihrer Szene eine SyncedRoom
-Komponente hinzu. Standardmäßig wird dabei die von Needle bereitgestellte Netzwerkinfrastruktur verwendet.
Fügen Sie einem Objekt, dessen Bewegung Sie über das Netzwerk synchronisieren möchten, eine SyncedTransform
-Komponente hinzu.
Fügen Sie dem gleichen Objekt eine DragControls
-Komponente hinzu.
Führen Sie das Projekt aus. Klicken Sie im Browser auf "Join Room" und kopieren Sie die URL.
Öffnen Sie ein neues Browserfenster und fügen Sie die URL ein. Sie sollten nun dasselbe Objekt in beiden Fenstern sehen. Versuchen Sie, das Objekt in einem Fenster zu ziehen und beobachten Sie, wie es sich im anderen Fenster bewegt.
Die DragControls
-Komponente, wie viele andere Needle-Komponenten auch, verfügt über integrierte Netzwerkunterstützung.
Die Besitzrechte werden an denjenigen übertragen, der mit dem Ziehen des Objekts beginnt.
SyncedRoom
Handhabt die Netzwerkverbindung und die Verbindung zu einem Raum.
SyncedTransform
Handhabt die Synchronisierung von Transformationen.
SyncedCamera
Erzeugt ein Prefab für jeden Benutzer, der mit dem Raum verbunden ist und dessen Position verfolgt.
VoIP
Handhabt Voice-over-IP-Audioverbindungen, Mikrofonzugriff usw. zwischen Benutzern.
ScreenCapture
Handhabt die Bildschirmfreigabe über Web-APIs.
Networking
Wird verwendet, um die URL des Server-Backends anzupassen. Ermöglicht auch die Einstellung eines lokalen Servers für die Entwicklung.
DragControls
Handhabt das Ziehen von Objekten. Die Besitzrechte werden automatisch an den letzten Benutzer übergeben, der ein Objekt zieht.
Duplicatable
Handhabt das Duplizieren von Objekten. Duplizierte Objekte werden für jeden im Raum instanziiert.
Deletable
Handhabt das Löschen von Objekten. Löschungen werden über das Netzwerk synchronisiert.
DeleteBox
Handhabt das Löschen von Objekten mit einer "Deletable"-Komponente, wenn sie in ein Quader-Volumen gezogen werden.
PlayerSync
Leistungsstarke Komponente, die für jeden verbundenen Spieler ein bestimmtes Objekt instanziiert.
PlayerState
Fügen Sie diese Komponente Objekten hinzu, die PlayerSync
zugewiesen sind.
PlayerColor
Einfache Komponente für spielerspezifische Farben. Jedem Benutzer wird beim Betreten eines Raumes eine zufällige Farbe zugewiesen. Diese Komponente weist diese Farbe dem Hauptmaterial des Objekts zu.
WebXR
Handhabt die Synchronisierung von Benutzeravataren (Hände und Köpfe).
Felder in Ihren eigenen Komponenten können sehr einfach vernetzt werden. Änderungen am Feld werden automatisch erkannt und an alle Benutzer im Raum gesendet. Die Änderungen werden auch als Teil des Raumzustands persistent gespeichert, sodass Benutzer, die später dem Raum beitreten, ebenfalls den aktuellen Zustand des Feldes erhalten und alle dieselben Daten sehen.
Um ein Feld in einer Komponente automatisch zu vernetzen, versehen Sie es mit dem @syncField()
-Decorator:
::::code-group :::code-group-item Synchronisieren einer Zahl
::: :::code-group-item Synchronisieren der Farbe eines Objekts
::: ::::
Beachten Sie, dass syncField
einen optionalen Parameter hat, um eine Methode anzugeben, die aufgerufen werden soll, wenn sich der Wert ändert. Diese Methode sollte in derselben Klasse definiert sein.
::: tip Benutzerdefiniertes Projekt-Setup
Wenn Sie ein benutzerdefiniertes Projekt-Setup verwenden, müssen Sie experimentalDecorators: true
in Ihrer tsconfig.json
-Datei aktivieren, damit syncField
-Decoratoren funktionieren. Projekte, die mit Needle Starters erstellt wurden, haben dies standardmäßig aktiviert.
:::
Oft möchten Sie Objekte zur Laufzeit erstellen und zerstören, und natürlich sollten diese Änderungen über das Netzwerk synchronisiert werden.
Die PlayerSync
-Komponente vereinfacht diesen Prozess, indem sie automatisch für jeden verbundenen Spieler ein bestimmtes Objekt instanziiert.
Wenn ein Spieler den Raum verlässt, wird das Objekt für alle Benutzer zerstört.
Zusätzlich stellt Needle Engine zwei High-Level-Methoden bereit:
🏗️ Codebeispiele im Aufbau
Needle Engine bietet auch eine Low-Level-API zum Senden und Empfangen von Nachrichten. Wir nennen dies "manuelle Vernetzung". Die Prinzipien sind dieselben, aber Sie haben die volle Kontrolle über das Senden und Empfangen von Nachrichten und deren Verarbeitung.
Senden einer Nachricht an alle Benutzer im selben Raum:
Sie können Ereignisse im Raum über einen bestimmten Schlüssel abonnieren. Typischerweise möchten Sie dies mit dem Abbestellen abgleichen:
abonnieren in onEnable
und abbestellen in onDisable
Mit diesem Ansatz werden keine Nachrichten empfangen, solange das Objekt deaktiviert ist.
oder abonnieren in start
und abbestellen in onDestroy
Mit diesem Ansatz werden Nachrichten weiterhin empfangen, auch wenn das Objekt deaktiviert ist.
Abbestellen von Ereignissen:
Beim Senden von Netzwerknachrichten können Sie über die Low-Level-API entscheiden, ob diese Nachricht persistent gespeichert (im Raumzustand gespeichert) oder nicht (nur an aktuell im Raum befindliche Benutzer gesendet) werden soll. Um eine Nachricht persistent zu speichern, stellen Sie sicher, dass sie ein guid
-Feld hat. Dieses Feld wird typischerweise verwendet, um die Nachrichtendaten auf ein bestimmtes Objekt anzuwenden, indem dessen guid
bereitgestellt wird. Wenn Sie ein bestimmtes Objekt ansprechen möchten (und somit ein guid
-Feld einschließen), aber die Daten nicht persistent speichern möchten, setzen Sie das dontSave
-Feld in Ihrer Nachricht auf true
.
Alle persistenten Nachrichten werden im Raumzustand gespeichert und an Benutzer gesendet, die sich später verbinden. Nicht-persistente Nachrichten werden nur an aktuell im Raum befindliche Benutzer gesendet, was nützlich für Effekte (wie das Abspielen eines Soundeffekts) ist, die für Benutzer, die aktuell nicht im Raum sind, keinen Sinn machen. Optional können Sie ein deleteOnDisconnect
-Feld in Ihre Nachricht aufnehmen, um diese spezielle Nachricht zu löschen, wenn sich der Benutzer trennt.
Um den Zustand für eine bestimmte guid
aus dem Backend-Speicher zu löschen, setzen Sie den Nachrichtenschlüssel auf delete-state
und zielen Sie mit dessen guid
auf ein bestimmtes Objekt: { guid: "guid_to_delete" }
.
Es gibt mehrere Debug-Flags, die verwendet werden können, um tiefer in die Netzwerknachrichten einzutauchen.
Diese können an die Seiten-URL angehängt werden, z.B. https://localhost:3000/?debugnet
.
?debugnet
Protokolliert alle eingehenden und ausgehenden Netzwerknachrichten in der Konsole
?debugowner
Protokolliert alle Besitzanfragen und -änderungen in der Konsole
?debugnetbin
Protokolliert zusätzliche Informationen für eingehende und ausgehende Binärnachrichten
Die folgenden Ereignisse stehen Ihnen zum Abhören in Ihren Komponenten zur Verfügung. Sie beschreiben allgemeine Netzwerkereignisse, auf die Sie in Ihren Komponenten reagieren möchten, z.B. wenn Sie selbst oder ein anderer Benutzer einem Raum beitritt oder ihn verlässt.
Standardmäßig verbinden sich vernetzte Needle-Szenen mit der von Needle verwalteten und bereitgestellten Cloud-Infrastruktur. Es ist keine zusätzliche Einrichtung erforderlich, und derzeit fallen keine zusätzlichen Kosten für die Nutzung dieses Dienstes an.
Typischerweise funktioniert dies gut für etwa 15-20 Benutzer im selben Raum. Sobald Ihr Projekt reifer wird, können Sie auf eine größere/bessere/stärkere Netzwerklösung umsteigen, indem Sie Ihren eigenen Netzwerkserver hosten.
Möglicherweise möchten Sie Ihren eigenen Netzwerkserver für größere Bereitstellungen hosten oder mehr Kontrolle über die Netzwerkinfrastruktur und -implementierung haben.
Die Standard-Glitch-Serverinstanz ist klein und kann nur eine begrenzte Anzahl von Benutzern verarbeiten. Wenn Sie erwarten, dass mehr als 15-20 Personen gleichzeitig in Ihrer Szene sind, sollten Sie erwägen, Ihren Netzwerkserver an anderer Stelle zu hosten (z.B. auf Google Cloud oder AWS). :::
::::code-group :::code-group-item Fastify
::: :::code-group-item Express
::: :::code-group-item Benutzerdefinierte Integration
::: ::::
::: tip Beispiel auf Glitch.com Den Code finden Sie auf [glitch.com/edit/#!/needle-networking?path=server.js] für ein Beispiel, wie man Needle Networking in einen Express-Server integriert. :::
Die folgenden Optionen sind verfügbar:
options.endpoint
string
Optional. Relativer Server-Endpunkt. Zum Beispiel startet /socket
den Websocket-Endpunkt auf ihrserver/socket
. Standard ist /
.
options.maxUsers
number
Maximale Anzahl gleichzeitiger Benutzer auf einem Server. Standard ist 50
.
options.defaultUserTimeout
number
Zeit in Sekunden, nach der ein Benutzer als getrennt betrachtet wird. Standard ist 30
.
process.env.VIEW_ONLY_SALT
string
Salt-Wert, der zur Generierung von Nur-Ansicht-Raum-IDs aus regulären Raum-IDs verwendet wird. Standard ist ein vordefinierter Salt-Wert.
process.env.NEEDLE_NETWORKING_S3_*
string
Aktiviert die S3-Speicherung. Siehe unten für die vollständige Liste der Umgebungsvariablen, die Sie dafür setzen müssen. Wenn nicht gesetzt, wird der Standardspeicher verwendet (JSON-Dateien auf der Festplatte).
Der Netzwerkserver verwaltet automatisch das Verbinden und Trennen von Benutzern, das Empfangen und Senden von Nachrichten und das Speichern des Raumzustands.
::: tip Unterschiedliche Serverstandorte für lokale und gehostete Entwicklung
Wenn Sie an benutzerdefiniertem Netzwerkcode arbeiten, möchten Sie möglicherweise unterschiedliche Serverstandorte für die lokale Entwicklung und die gehostete App verwenden. Sie können individuelle Server-URLs in der Networking
-Komponente festlegen:
Der Netzwerkzustand wird standardmäßig als JSON-Dateien auf der Festplatte des Servers im Verzeichnis /.data
gespeichert.
Jeder Raum hat seine eigene Datei, und der Zustand wird beim Beitritt zu einem Raum an verbindende Clients gesendet.
Optional kann der Netzwerkzustand bei einem S3-kompatiblen Speicheranbieter gespeichert werden. Verwenden Sie die folgenden Umgebungsvariablen, um die S3-Speicherung zu aktivieren:
Für Test- und Entwicklungszwecke können Sie das Needle Engine Netzwerkpaket auf einem lokalen Server ausführen. Wir haben ein Repository vorbereitet, das für das Hosting des Websocket-Pakets eingerichtet ist, um Ihnen dies zu erleichtern.
Befolgen Sie die Anweisungen in der README, um den Server einzurichten. Der Server läuft standardmäßig auf wss://localhost:9001/socket
.
Fügen Sie die Networking
-Komponente zu Ihrer Szene hinzu.
Fügen Sie die lokale Serveradresse in das Feld Localhost
der Networking
-Komponente ein.
Needle Engine verwendet vernünftige Standardeinstellungen für peerjs. Wenn Sie diese Standardeinstellungen ändern möchten, können Sie
mit Ihren benutzerdefinierten Einstellungen aufrufen. Dies kann verwendet werden, um den Hosting-Anbieter für ICE/STUN/TURN-Server zu ändern, z.B. wenn Sie Ihre eigenen WebRTC-Server verwenden.
::: warning Nur zu Informationszwecken. Verwenden Sie stattdessen die von Needle Engine bereitgestellten APIs. Typischerweise müssen Sie nicht direkt mit diesen Nachrichtenformaten interagieren, da die Low-Level-Networking-API das Parsen von Nachrichten und die Bereitstellung der korrekten Typen bereits handhabt. Die Informationen hier sind für fortgeschrittene Benutzer gedacht, die die zugrunde liegenden Nachrichtenformate verstehen oder eigene Netzwerklösungen implementieren möchten. :::
Nachrichten werden im JSON-Format gesendet. Sie haben immer ein Feld key
, das den Nachrichtentyp beschreibt, und ein Feld data
, das die Nutzlast der Nachricht enthält. Das data
-Feld kann jedes JSON-serialisierbare Objekt sein.
::::code-group :::code-group-item Beitritt
::: :::code-group-item Verlassen
::: :::code-group-item Raum beigetreten
::: :::code-group-item Raum verlassen
::: :::code-group-item Benutzer Raum beigetreten
::: :::code-group-item Benutzer Raum verlassen
::: :::code-group-item Raumzustand gesendet
::: ::::
::::code-group :::code-group-item Verbindungsinformationen
::: :::code-group-item syncInstantiate
::: :::code-group-item syncDestroy
::: :::code-group-item Ping
::: :::code-group-item Pong
::: :::code-group-item Zustand löschen
::: :::code-group-item Gesamten Zustand löschen
::::
::::code-group :::code-group-item Besitzanfrage
::: :::code-group-item Besitzantwort // Typ: OwnershipResponse
::: ::: code-group-item Besitz-Broadcast-Antwort
::: ::::
Flatbuffer-Nachrichten werden direkt als Binärnachrichten gesendet.
::::code-group :::code-group-item SyncedTransform ('STRS')
::: :::code-group-item SyncedCamera ('SCAM')
::: :::code-group-item Vec2|3|4
::: ::::
JSON-Nachrichten sind einfach zu verwenden und zu verstehen, benötigen aber typischerweise mehr Speicher und Bandbreite. Für große Datenmengen oder beim Senden schneller Updates sind Binärnachrichten schneller und effizienter. Sie können Flatbuffers-Nachrichten in Needle Engine für Fälle verwenden, in denen dies erforderlich ist. Die Verwendung von Flatbuffers erfordert zusätzliche Einrichtungsschritte wie das Definieren und Kompilieren eines Nachrichtenschemas und ist schwieriger zu debuggen, da Sie mit Binärnachrichten arbeiten.
Beachten Sie, dass beim Senden und Empfangen von Flatbuffer-Nachrichten kein key
-Feld vorhanden ist – der Nachrichtentyp ist Teil des Flatbuffer-Schemas. Was Sie über die Websocket-Verbindung senden und empfangen, ist ein einziger Binärpuffer.
Senden einer Binärnachricht an alle Benutzer im selben Raum:
Abonnieren von Binärnachrichten im Flatbuffer-Format:
Abbestellen von Binärnachrichten:
Bevor Sie Flatbuffer-Nachrichten senden und empfangen können, müssen Sie ein Schema definieren und in TypeScript kompilieren. Anschließend registrieren Sie das Schema beim Netzwerksystem und verwenden die generierten Schema-Methoden zum Erstellen und Parsen von Nachrichten.
::::code-group :::code-group-item Ein Schema registrieren
::: :::code-group-item Nachrichten senden
::: :::code-group-item Nachrichten empfangen
::: ::::
::: tip Benutzerdefinierte Flatbuffer-Nachrichten und Persistenz Derzeit können benutzerdefinierte Binärnachrichten nicht auf dem Netzwerkserver gespeichert werden. Ändern Sie den Netzwerkserver und fügen Sie Ihre benutzerdefinierten Flatbuffer-Schemata hinzu, um sicherzustellen, dass die guid-Eigenschaft verarbeitet werden kann. :::
Needle Engine macht das komplexe Thema der Vernetzung zugänglich und einfach zu bedienen. Sie können mit der automatischen Vernetzung Ihrer Komponenten mit nur wenigen Codezeilen beginnen und tiefer in die manuelle Vernetzung eintauchen, wenn Sie mehr Kontrolle benötigen.
Seite automatisch mit KI übersetzt
zum Duplizieren von Objekten über das Netzwerk.
zum Zerstören von Objekten über das Netzwerk.
Unser Netzwerkserver ist auf NPM als node.js-Paket verfügbar: . Das Paket enthält vorkonfigurierte Integrationen für die beliebten Web-Frameworks und und kann auch in andere Node.js-Server-Frameworks integriert werden.
::: tip Für schnelle Experimente: Remix auf Glitch Sie können einen einfachen Netzwerkserver, der auf Glitch läuft, von dieser Seite remixen: , indem Sie auf die Schaltfläche unten rechts klicken.
Benutzerdefinierte Netzwerkserver können überall bereitgestellt werden, z.B. auf Google Cloud. Weitere Anweisungen finden Sie in diesem Repository:
:::
Laden Sie das Beispiel für den lokalen Server von herunter.
Die Needle Engine-Komponenten Screencapture
(Bildschirmfreigabe) und VoIP
(Sprachkommunikation) verwenden für die Vernetzung von Audio und Video. Peer.js verwendet unter der Haube WebRTC.