Ein Browser-Plugin für Unity

Die Entwicklungstools und die Engine von Unity sind heute bei weitem der häufigste Weg, um Anwendungen für VR und AR zu erstellen. Bisher haben wir es möglich gemacht, webbasierte Erfahrungen aus Unity zu exportieren. Heute freuen wir uns, einige frühe Arbeiten zu zeigen, die sich mit der anderen Art und Weise befassen, wie Unity-Entwickler das Web nutzen wollen: als Komponente in ihren Unity-basierten virtuellen Umgebungen.

Aufbauend auf unserer Arbeit, eine Browser-Engine auf viele Plattformen und Einbettungsszenarien zu portieren, einschließlich als Firefox Reality AR für HoloLens 2, haben wir eine neue Unity-Komponente auf der Grundlage von Servo gebaut, einer modernen Web-Engine, die in der Sprache Rust geschrieben wurde.

Die Unity-Engine verfügt über ein sehr anpassungsfähiges Multiplattform-Plugin-System mit einem gesunden Ökosystem von Drittanbieter-Plugins, sowohl Open-Source als auch proprietär. Das Plugin-System ermöglicht es uns, OS-native Module auszuführen und sie direkt mit Komponenten zu verbinden, die in der Unity-Skriptumgebung ausgeführt werden.

Ziel der Experimente war es, ein natives Unity-Plugin und eine Reihe von Unity-C#-Skriptkomponenten zu entwickeln, die es Dritten ermöglichen, Servo-Browserfenster in Unity-Szenen einzubinden und optional Unterstützung für die Verwendung der Browseroberfläche in VR- und AR-Apps zu bieten, die in Unity erstellt wurden.

Heute veröffentlichen wir einen voll funktionsfähigen Prototyp des Servo-Webbrowsers, der in einem Unity-Plugin läuft. Dies ist ein früher Einblick in unsere Arbeit, aber wir wissen, dass die Begeisterung für diese Art von Lösung groß ist, daher hoffen wir, dass Sie diesen Prototyp ausprobieren, uns Ihr Feedback geben und mit uns zusammen Dinge damit bauen. Die heute veröffentlichte Version zielt auf die macOS-Plattform ab, aber wir werden sehr bald einige der anderen von Servo unterstützten Plattformen hinzufügen.

Anfangen

Wir haben das Plugin unter https://github.com/MozillaReality/servo-unity als Open-Source zur Verfügung gestellt. Klickt auf den Stern und forkt den Code, checkt ihn auf eurem lokalen Rechner aus und öffnet das Projekt in Unity.

Anweisungen für Entwickler befinden sich in der READMEDatei im Repository.

Was es macht

Sie können direkt mit dem Browserfenster und den Steuerelementen innerhalb des Unity-Editors arbeiten. Die Top-Level-Konfiguration befindet sich auf dem ServoUnityController Objekt. Andere wichtige Objekte in der Szene sind ServoUnityWindow, ServoUnityNavbarController und ServoUnityMousePointer.

Das ServoUnityWindow kann überall in einer Unity-Szene positioniert werden. Hier haben wir es in die Mozilla-Pilzhöhle gesetzt (bekannt für Nutzer von Firefox Reality, von der erstaunlichen Künstlerin Jasmin Habezai-Fekri) und einen Kameramanipulator bereitgestellt, der es uns ermöglicht, uns in der Szene zu bewegen und zu sehen, dass es sich um eine 3D-Ansicht des Browserinhalts handelt.

Servo verfügt über eine hochwertige Medienwiedergabe über das GStreamer-Framework, einschließlich Audio-Unterstützung. Hier sehen wir ein Beispiel für ein MPEG4-Video, das in einem bereitgestellten Unity-Player-Build läuft.

Das Plugin enthält eine anpassbare Suche. Eine Vielzahl von Webinhalten kann mit der aktuellen Version von Servo angezeigt werden, wobei aktiv an einer größeren Webkompatibilität gearbeitet wird (mehr dazu weiter unten). WebGL-Inhalte funktionieren ebenfalls.

Wie es funktioniert

Architektur

Die Entwicklung in Unity verwendet eine komponentenbasierte Architektur, bei der Unity Benutzercode ausführt, der an GameObjects angehängt und in Szenen organisiert ist. Benutzer passen GameObjects an, indem sie Skripte anhängen, die in einer C#-Umgebung ausgeführt werden, entweder mit der Mono-Laufzeit oder dem IL2CPP-Ahead-of-Time-Compiler. Der Unity-Ereignislebenszyklus ist für Benutzerskripte zugänglich, die von der Unity-C#-Klasse MonoBehaviour erben. Benutzerskripte können über den P/Invoke-Mechanismus der C#-Laufzeitumgebung nativen Code in Plugins aufrufen (bei denen es sich lediglich um OS-native dynamische Shared Objects handelt). Tatsächlich ist der Kern von Unity selbst in C++ implementiert und bietet nativen Code in Plugins mit einem zweiten Satz von C/C++-zugänglichen Schnittstellen, um bei einigen Low-Level-Plugin-Aufgaben zu helfen.

Servo ist selbst ein komplexes Stück Software. Der größte Teil der Funktionalität, die nicht für den Benutzer bestimmt ist, wurde in eine Rust-Bibliothek libservo kompiliert. In dieser ersten Phase des Projekts nutzen wir eine vereinfachte C-kompatible Schnittstelle in einer anderen Rust-Bibliothek namens libsimpleservo2.. Diese Bibliothek stellt C-aufrufbare Funktionen und Callback-Hooks zur Verfügung, um den Browser zu steuern und seine Ausgaben anzuzeigen. Um libsimpleservo2 herum setzen wir native C++-Abstraktionen ein, die das Unity-Modell von Threads und Rendering kapseln und eine Reihe von Unity-aufrufbaren Schnittstellen bereitstellen, die wiederum von unseren C#-Skriptkomponenten bedient werden.

Browser-Inhalte in Unity einbinden

Wir erstellen ein Objekt in Unity, eine Instanz von ServoUnityWindow, um eine Instanz der Texture2D-Klasse von Unity zu umhüllen und sie als Browser-Inhaltsfenster zu behandeln. Bei der Verwendung von Unitys OpenGL-Renderer wird die Klasse Texture2D von einer nativen OpenGL-Textur unterstützt, und wir übergeben den OpenGL-Textur-„Namen“ (d. h. eine ID) an das Plugin, das die Textur an ein Framebuffer-Objekt bindet, das die endgültige zusammengesetzte Textur von Servo erhält.

Da wir keine Kontrolle über die Bindung der Textur und den Unity-Kontext haben, verwendet das aktuelle Design zur Aktualisierung dieser Textur einen Blit (Kopie) über Servos surfman-chains API. Im Wesentlichen schreibt Servos WebRender in einen OS-spezifischen Oberflächenpuffer auf einem Thread, und dann wird dieser Oberflächenpuffer schreibgeschützt an den Render-Thread von Unity gebunden, und eine Texturkopie wird mithilfe von OpenGL-APIs erstellt. In der anfänglichen macOS-Implementierung ist der Oberflächenpuffer beispielsweise ein IOSurface, der zum Nulltarif zwischen Threads verschoben werden kann, was eine effiziente Implementierung ermöglicht, bei der der Browser-Compositor in einem anderen Thread schreiben kann als der Thread, der die Textur in Unity anzeigt.

Steuerungs- und Seiten-Metadaten werden separat über eine Reihe von APIs kommuniziert, die die Suche und Navigation zu URLs, die Aktualisierung von Seitentiteln und die übliche Zurück/Vorwärts/Stop/Home-Taste ermöglichen.

Da die Inhalte und Steuerelemente des Browsers letztendlich alle Unity-Objekte sind, kann die Unity-Anwendung, die Sie erstellen, diese auf jede beliebige Weise positionieren, gestalten oder programmatisch steuern.

Herausforderungen

Das Projekt bis zu diesem Stadium zu bringen, war nicht ohne Herausforderungen, von denen wir einige immer noch angehen. Die Skripting-Umgebung von Unity läuft größtenteils im Single-Thread-Verfahren, mit Ausnahme der Rendering-Operationen, die auf einem separaten Thread in einem anderen Rhythmus ablaufen. Servo hingegen erzeugt potenziell Dutzende von leichtgewichtigen Threads für eine Vielzahl von Aufgaben. Wir haben dafür gesorgt, dass die von Servo zurückkehrenden Arbeitselemente den richtigen Threads in Unity zugewiesen werden. Es gibt noch einige Optimierungen bei der Entscheidung, wann die Unity-Textur aktualisiert werden soll. Derzeit wird sie einfach bei jedem Frame aktualisiert, aber wir fügen eine API zur Einbettungsschnittstelle hinzu, um eine feinere Steuerung zu ermöglichen.

Als Inkubator für Browsertechnologie konzentriert sich Servo auf die Entwicklung neuer Technologien. Zu den bemerkenswerten Technologien, die von Servo in die Gecko-Engine von Firefox übergegangen sind, gehören die GPU-basierte Rendering-Engine WebRender und die CSS-Engine Stylo. Abgesehen von diesen Erfolgen ist die vollständige Webkompatibilität immer noch ein Bereich, in dem Servo eine erhebliche Lücke aufweist, da wir uns in erster Linie auf große Verbesserungen für den Benutzer und spezifische Erfahrungen im Long Tail des Webs konzentriert haben. Eine kürzliche Anstrengung der Servo-Community hat zu großen Fortschritten in Servos Webkompatibilität geführt, so dass wir erwarten, dass die Teilmenge des Webs, die von Servo durchstöbert werden kann, weiterhin schnell wachsen wird.

Entwicklungspläne

Die Unterstützung aller Plattformen, die derzeit von Servo unterstützt werden, ist unsere erste Entwicklungspriorität, wobei die Unterstützung von Windows Win32 und Windows UWP ganz oben auf der Liste steht. Viele von Ihnen haben unsere Firefox Reality AR for HoloLens 2 App gesehen, und die UWP-Unterstützung wird es Ihnen ermöglichen, Servo in Ihre eigenen AR-Apps für die HoloLens-Plattform einzubauen, indem Sie dieselbe zugrunde liegende Browser-Engine verwenden.

Wir würden auch gerne eine größere Teilmenge der vollen Browser-Fähigkeit unterstützen. Ganz oben auf der Liste steht die Unterstützung von mehreren Fenstern. Wir arbeiten derzeit daran, das Plugin von der libsimpleservo2-Schnittstelle zu einer neuen Schnittstelle zu graduieren, die es Anwendungen ermöglicht, mehrere Fenster und Tabs zu instanziieren und Funktionen wie Verlauf, Lesezeichen und mehr zu implementieren.

Diese erste Version konzentriert sich auf das Web, das durch 2D-Webseiten durchstöbert werden kann. Servo unterstützt auch das immersive Web durch die WebXR-API, und wir untersuchen die Verbindung von WebXR mit der XR-Hardwareunterstützung von Unity durch die Plugin-Schnittstelle. Wir werden mit der Unterstützung für das Betrachten von 360°-Videos beginnen, was, wie wir von unserer Firefox Reality-Basis wissen, ein Hauptanwendungsfall für den Browser ist.

Schließlich…

Ob als Media-Player, als In-Game-Interface zum offenen Web, als Browser-as-UI, zum Einbinden spezifischer Web-Erfahrungen oder für die unzähligen anderen Möglichkeiten, wir können es kaum erwarten, einige der fantasievollen Wege zu sehen, wie Entwickler die Kraft und Leistung von Servo in Unity-entwickelten Anwendungen nutzen werden.