Un plugin de navigateur pour Unity

Les outils et le moteur de développement d’Unity sont de loin le moyen le plus courant de créer des applications pour la RV et la RA aujourd’hui. Auparavant, nous avons rendu possible l’exportation d’expériences web à partir d’Unity. Aujourd’hui, nous sommes ravis de montrer quelques travaux préliminaires abordant l’autre façon dont les développeurs Unity veulent utiliser le web : en tant que composant dans leurs environnements virtuels basés sur Unity.

S’appuyant sur notre travail de portage d’un moteur de navigateur vers de nombreuses plateformes et scénarios d’intégration, y compris comme Firefox Reality AR pour HoloLens 2, nous avons construit un nouveau composant Unity basé sur Servo, un moteur web moderne écrit dans le langage Rust.

Le moteur Unity possède un système de plugins multiplateformes très adaptable avec un écosystème sain de plugins tiers, à la fois open-source et propriétaires. Le système de plugins nous permet d’exécuter des modules natifs de l’OS et de les connecter directement aux composants s’exécutant dans l’environnement de script Unity.

Les objectifs des expériences étaient de construire un plugin natif Unity et un ensemble de composants de script C# Unity qui permettraient à des tiers d’incorporer des fenêtres de navigateur Servo dans des scènes Unity, et éventuellement, de fournir un support pour l’utilisation de la surface du navigateur dans des applications VR et AR construites dans Unity.

Aujourd’hui, nous publions un prototype entièrement fonctionnel du navigateur web Servo fonctionnant à l’intérieur d’un plugin Unity. Il s’agit d’un aperçu précoce de notre travail, mais nous savons que l’excitation est grande pour ce type de solution, alors nous espérons que vous essaierez ce prototype, que vous nous ferez part de vos commentaires et que vous nous rejoindrez pour construire des choses avec. La version publiée aujourd’hui cible la plateforme macOS, mais nous ajouterons très bientôt certaines des autres plateformes prises en charge par Servo.

Mise en route

Nous avons mis le plugin en open-source, à https://github.com/MozillaReality/servo-unity. Allez-y, cliquez sur l’étoile et fork le code, vérifiez-le sur votre machine locale, puis ouvrez le projet à l’intérieur d’Unity.

Les instructions pour les développeurs sont dans le fichier README du dépôt.

Ce qu’il fait

Vous pouvez travailler directement avec la fenêtre du navigateur et les contrôles à l’intérieur de l’éditeur Unity. La configuration de haut niveau se trouve sur l’objet ServoUnityController. Les autres objets importants de la scène comprennent le ServoUnityWindow, le ServoUnityNavbarController et le ServoUnityMousePointer.

Le ServoUnityWindow peut être positionné n’importe où dans une scène Unity. Ici, nous l’avons déposé dans la grotte champignon de Mozilla (familière aux utilisateurs de Firefox Reality, par l’incroyable artiste Jasmin Habezai-Fekri), et fourni un manipulateur de caméra qui nous permet de nous déplacer dans la scène et de voir qu’il s’agit d’une vue 3D du contenu du navigateur.

Servo possède une lecture multimédia de haute qualité via le framework GStreamer, y compris le support audio. Ici, nous visualisons un échantillon de vidéo MPEG4, s’exécutant à l’intérieur d’une build de lecteur Unity déployée.

Une recherche personnalisable est incluse dans le plugin. Une grande variété de contenu web est visualisable avec la version actuelle de Servo, une plus grande compatibilité web étant activement travaillée (plus à ce sujet ci-dessous). Le contenu WebGL fonctionne également.

Comment ça marche

Architecture

Le développement dans Unity utilise une architecture basée sur des composants, où Unity exécute le code utilisateur attaché à des GameObjects, organisés en scènes. Les utilisateurs personnalisent les GameObjects en attachant des scripts qui s’exécutent dans un environnement C#, soit en utilisant le runtime Mono, soit le compilateur en avance sur le temps IL2CPP. Le cycle de vie des événements Unity est accessible aux scripts utilisateur héritant de la classe C# Unity MonoBehaviour. Les scripts utilisateurs peuvent invoquer du code natif dans les plugins (qui ne sont que des objets dynamiques partagés natifs du système d’exploitation) via le mécanisme P/Invoke du runtime C#. En fait, le noyau d’Unity lui-même est implémenté en C++ et fournit au code natif des plugins un deuxième ensemble d’interfaces accessibles en C/C++ pour aider à certaines tâches de bas niveau des plugins.

Servo est lui-même un logiciel complexe. Par conception, la plupart de ses fonctionnalités non tournées vers l’utilisateur sont compilées dans une bibliothèque Rust, libservo. Pour cette première phase du projet, nous utilisons une interface simplifiée compatible C dans une autre bibliothèque Rust nommée libsimpleservo2.. Cette bibliothèque expose des fonctions appelables en C et des crochets de rappel pour contrôler le navigateur et visualiser sa sortie. Autour de libsimpleservo2, nous mettons en place des abstractions C++ natives qui encapsulent le modèle Unity des threads et du rendu, et exposent un ensemble d’interfaces appelables par Unity qui sont à leur tour exploitées par nos composants de script C#.

Mettre le contenu du navigateur dans Unity

Nous créons un objet dans Unity, une instance de ServoUnityWindow, pour envelopper une instance de la classe Texture2D de Unity et la traiter comme un volet de contenu du navigateur. Lorsque l’on utilise le moteur de rendu OpenGL de Unity, la classe Texture2D est soutenue par une texture OpenGL native, et nous passons le « nom » de la texture OpenGL (c’est-à-dire un ID) au plugin, qui lie la texture à un objet framebuffer qui reçoit la texture finale composée de Servo.

Comme nous n’avons pas le contrôle sur la liaison de la texture et du contexte Unity, la conception actuelle pour mettre à jour cette texture utilise un blit (copie) via l’API surfman-chains de Servo. Essentiellement, le WebRender de Servo écrit dans un tampon de surface spécifique au système d’exploitation sur un thread, puis ce tampon de surface est lié en lecture seule au thread de rendu d’Unity et une copie de la texture est effectuée en utilisant les API OpenGL. Dans l’implémentation initiale de macOS par exemple, le tampon de surface est un IOSurface qui peut être déplacé à coût zéro entre les threads, permettant une implémentation efficace où le compositeur du navigateur peut écrire dans un thread différent du thread affichant la texture dans Unity.

Les méta-données de contrôle et de page sont communiquées séparément, via un ensemble d’API qui permettent la recherche et la navigation vers les URL, la mise à jour des titres de page, et l’ensemble habituel de boutons retour/avance/arrêt/accueil.

Parce que le contenu et les contrôles du navigateur sont tous, en fin de compte, des objets Unity, l’application Unity que vous construisez peut les positionner, les styliser ou les contrôler par programmation de la manière que vous souhaitez.

Défis

Parvenir à ce stade du projet n’a pas été sans défis, dont certains sont encore en cours de traitement. L’environnement de script d’Unity fonctionne en grande partie en single-thread, à l’exception des opérations de rendu qui ont lieu sur un thread séparé à une cadence différente. Servo, cependant, génère potentiellement des dizaines de threads légers pour une variété de tâches. Nous avons pris soin d’acheminer les éléments de travail de Servo vers les bons threads dans Unity. Il reste quelques optimisations à faire pour décider quand rafraîchir la texture d’Unity. Actuellement, elle se rafraîchit simplement à chaque image, mais nous ajoutons une API à l’interface d’intégration pour permettre un contrôle plus fin.

En tant qu’incubateur pour la technologie des navigateurs, Servo se concentre sur le développement de nouvelles technologies. Parmi les technologies notables qui sont passées de Servo au moteur Gecko équipant Firefox figurent le moteur de rendu basé sur le GPU, WebRender, et le moteur CSS Stylo. Ces succès mis à part, la compatibilité totale avec le Web reste un domaine dans lequel Servo présente des lacunes importantes, car nous nous sommes principalement concentrés sur les grandes améliorations pour l’utilisateur et les expériences spécifiques sur la longue traîne du Web. Un effort récent de la communauté Servo a vu de grandes avancées dans le webcompat de Servo, donc nous nous attendons à ce que le sous-ensemble du web navigable par Servo continue de croître rapidement.

Plans de développement

Le support de la gamme complète de plateformes actuellement supportées par Servo est notre première priorité de développement de suivi, avec le support de Windows Win32 et Windows UWP en haut de la liste. Beaucoup d’entre vous ont vu notre application Firefox Reality AR pour HoloLens 2, et le support UWP vous permettra d’intégrer Servo dans une de vos propres applications AR pour la plateforme HoloLens en utilisant le même moteur de navigateur sous-jacent.

Nous aimerions également supporter un plus grand sous-ensemble de la capacité complète du navigateur. En haut de la liste se trouve le support des fenêtres multiples. Nous travaillons actuellement sur la graduation du plugin de l’interface libsimpleservo2 à une nouvelle interface qui permettra aux applications d’instancier plusieurs fenêtres, onglets, et d’implémenter des fonctionnalités comme l’historique, les signets et plus encore.

Cette première version est axée sur le web navigable à travers des pages web 2D. Servo prend également en charge le web immersif à travers l’API WebXR, et nous explorons la connexion de WebXR au support matériel XR d’Unity à travers l’interface du plugin. Nous commencerons par le support de la visualisation de vidéos à 360°, dont nous savons, grâce à notre base d’utilisateurs de Firefox Reality, qu’il s’agit d’un cas d’utilisation privilégié pour le navigateur.

Enfin…

Qu’il s’agisse d’un lecteur multimédia, d’une interface de jeu vers le web ouvert, d’un navigateur en tant qu’interface utilisateur, de l’apport d’expériences web spécifiques, ou de la myriade d’autres possibilités, nous sommes impatients de voir certaines des façons imaginatives dont les développeurs exploiteront la puissance et les performances de Servo à l’intérieur des applications construites par Unity.