Ett webbläsarplugin för Unity

Unitys utvecklingsverktyg och motor är det överlägset vanligaste sättet att bygga program för VR och AR idag. Tidigare har vi gjort det möjligt att exportera webbaserade upplevelser från Unity. Idag är vi glada att kunna visa ett tidigt arbete som tar upp det andra sättet som Unity-utvecklare vill använda webben på: som en komponent i sina Unity-baserade virtuella miljöer.

Med utgångspunkt i vårt arbete med att portera en webbläsarmotor till många plattformar och inbäddningsscenarier, bland annat som Firefox Reality AR för HoloLens 2, har vi byggt en ny Unity-komponent som är baserad på Servo, en modern webbmotor som är skriven i språket Rust.

Unity-motorn har ett mycket anpassningsbart plugin-system för flera plattformar med ett hälsosamt ekosystem av plugins från tredje part, både med öppen källkod och egenutvecklade. Pluginsystemet gör det möjligt för oss att köra OS-nativa moduler och ansluta dem direkt till komponenter som körs i Unitys skriptmiljö.

Målen med experimenten var att bygga ett Unity-inhemskt insticksprogram och en uppsättning Unity C#-skriptkomponenter som skulle göra det möjligt för tredje part att införliva Servo-webbläsarfönster i Unity-scener och eventuellt ge stöd för att använda webbläsarytan i VR- och AR-appar som byggs i Unity.

I dag släpper vi en fullt fungerande prototyp av Servo-webbläsaren som körs i ett Unity-insticksprogram. Detta är en tidig inblick i vårt arbete, men vi vet att spänningen är stor för den här typen av lösning, så vi hoppas att du vill prova prototypen, ge din feedback och ansluta dig till oss för att bygga saker med den. Den version som släpps idag är inriktad på macOS-plattformen, men vi kommer att lägga till några av de andra plattformarna som stöds av Servo mycket snart.

Sätt igång

Vi har öppnat insticksmodulen, på https://github.com/MozillaReality/servo-unity. Gå dit, klicka på stjärnan och gaffel koden, kolla in den på din lokala maskin och öppna sedan projektet i Unity.

Instruktioner för utvecklare finns i README-filen i repositoriet.

Vad den gör

Du kan arbeta direkt med webbläsarfönstret och kontrollerna inne i Unity Editor. Konfigurationen på högsta nivå finns på ServoUnityController-objektet. Andra viktiga objekt i scenen är ServoUnityWindow, ServoUnityNavbarController och ServoUnityMousePointer.

ServoUnityWindow kan placeras var som helst i en Unityscen. Här har vi släppt den i Mozillas svampgrotta (bekant för användare av Firefox Reality, av den fantastiska konstnären Jasmin Habezai-Fekri) och tillhandahållit en kameramanipulator som gör att vi kan röra oss i scenen och se att det är en 3D-vy av innehållet i webbläsaren.

Servo har högkvalitativ uppspelning av media via GStreamer-ramverket, inklusive ljudstöd. Här visar vi exempel på MPEG4-video som körs i ett distribuerat Unity-spelarbygge.

Anpassningsbar sökning ingår i insticksmodulen. Ett brett utbud av webbinnehåll kan visas med den nuvarande versionen av Servo, med större webbkompatibilitet som det aktivt arbetas med (mer om det nedan). WebGL-innehåll fungerar också.

Hur det fungerar

Arkitektur

Utvecklingen i Unity använder sig av en komponentbaserad arkitektur, där Unity exekverar användarkod som är kopplad till GameObjects, organiserade i scener. Användarna anpassar GameObjects genom att bifoga skript som exekveras i en C#-miljö, antingen med hjälp av Mono runtime eller IL2CPP ahead-of-time compiler. Unity-händelsernas livscykel är tillgänglig för användarskript som ärver från Unity C#-klassen MonoBehaviour. Användarskript kan anropa inhemsk kod i plugins (som bara är OS-nativa dynamiska delade objekt) via C#-körningstidens P/Invoke-mekanism. Unitys kärna är i själva verket implementerad i C++ och förser inhemsk kod i plugins med en andra uppsättning gränssnitt som är tillgängliga i C/C++ för att hjälpa till med vissa uppgifter på låg nivå för plugins.

Servo är i sig självt en komplicerad mjukvara. Av designen är det mesta av dess icke användarvänliga funktionalitet kompilerad till ett Rust-bibliotek, libservo. I den här första fasen av projektet använder vi oss av ett förenklat C-kompatibelt gränssnitt i ett annat Rust-bibliotek som heter libsimpleservo2. Detta bibliotek exponerar C-kallbara funktioner och callbackkrokar för att styra webbläsaren och visa dess utdata. Runt libsimpleservo2 inför vi inhemska C++-abstraktioner som kapslar in Unity-modellen för trådar och rendering och exponerar en uppsättning gränssnitt som kan anropas av Unity och som i sin tur används av våra C#-skriptkomponenter.

Hitta in webbläsarinnehållet i Unity

Vi skapar ett objekt i Unity, en instans av ServoUnityWindow, för att omsluta en instans av Unitys Texture2D-klass och behandla den som en innehållsruta i webbläsaren. När vi använder Unitys OpenGL-renderare stöds Texture2D-klassen av en inhemsk OpenGL-textur, och vi skickar OpenGL-texturens ”namn” (dvs. ett ID) till insticksmodulen, som binder texturen till ett framebuffer-objekt som tar emot den slutliga sammansatta texturen från Servo.

Då vi inte har kontroll över bindningen av texturen och Unity-kontexten använder den nuvarande utformningen för uppdatering av denna textur en blit (kopia) via Servos surfman-chains API. I huvudsak skriver Servos WebRender till en OS-specifik ytbuffert på en tråd, och sedan binds denna ytbuffert skrivskyddad till Unitys rendertråd och en texturkopia görs med hjälp av OpenGL API:er. I den ursprungliga macOS-implementationen är ytbufferten till exempel en IOSurface som kan flyttas till nollkostnad mellan trådar, vilket möjliggör en effektiv implementering där webbläsarens kompositör kan skriva i en annan tråd än den tråd som visar texturen i Unity.

Kontroll- och sidmetadata kommuniceras separat via en uppsättning API:er som möjliggör sökning och navigering till webbadresser, uppdatering av sidtitlar och de vanliga knapparna för bakåt/framåt/stopp/hemma.

Då webbläsarens innehåll och kontroller i slutändan alla är Unity-objekt, kan den Unity-applikation du bygger placera, styra eller programmatiskt styra dessa på vilket sätt som helst.

Utmaningar

Att få projektet till det här stadiet har inte varit utan utmaningar, och vi håller fortfarande på att ta itu med en del av dem. Unitys skriptmiljö körs i stort sett med en enda tråd, med undantag för renderingsoperationer som sker på en separat tråd i en annan kadens. Servo skapar dock potentiellt dussintals lättviktiga trådar för en mängd olika uppgifter. Vi har sett till att återkommande arbetsmoment från Servo återförs till rätt trådar i Unity. Det finns några återstående optimeringar att göra när det gäller att bestämma när Unity-texturen ska uppdateras. För närvarande uppdateras den bara varje bildruta, men vi lägger till ett API till inbäddningsgränssnittet för att möjliggöra finkornigare kontroll.

Servo är en inkubator för webbläsarteknik och fokuserar på att utveckla ny teknik. Bland den teknik som flyttats från Servo till Gecko-motorn i Firefox finns den GPU-baserade renderingsmotorn WebRender och CSS-motorn Stylo. Bortsett från dessa framgångar är fullständig webbkompatibilitet fortfarande ett område där Servo har en betydande lucka, eftersom vi i första hand har fokuserat på stora förbättringar för användaren och specifika upplevelser över webbens långa svans. En nyligen genomförd insats av Servo-gemenskapen har inneburit stora framsteg i Servos webbkompatibilitet, så vi förväntar oss att den delmängd av webben som Servo kan bläddra i kommer att fortsätta att växa snabbt.

Utvecklingsplaner

Att ge stöd för alla de plattformar som för närvarande stöds av Servo är vår första uppföljande utvecklingsprioritering, med Windows Win32- och Windows UWP-stödet högst upp på listan. Många av er har sett vår Firefox Reality AR for HoloLens 2-app, och UWP-stödet kommer att göra det möjligt att bygga in Servo i egna AR-appar för HoloLens-plattformen med hjälp av samma underliggande webbläsarmotor.

Vi skulle också vilja stödja en större delmängd av den fullständiga webbläsarkapaciteten. Högt på listan står stöd för flera fönster. Vi arbetar för närvarande med att gradera insticksmodulen från libsimpleservo2-gränssnittet till ett nytt gränssnitt som gör det möjligt för program att instansiera flera fönster, flikar och implementera funktioner som historik, bokmärken med mera.

Denna första utgåva fokuserar på webben som kan bläddras genom 2D-webbsidor. Servo stöder också den uppslukande webben genom WebXR API:et, och vi undersöker möjligheten att ansluta WebXR till Unitys XR-hårdvarustöd genom plugin-gränssnittet. Vi kommer att börja med stöd för visning av 360°-video, vilket vi vet från våra Firefox Reality-användare är ett utmärkt användningsområde för webbläsaren.

Enligt…

Oavsett om det är en mediaspelare, ett gränssnitt för den öppna webben i ett spel, en webbläsare som användargränssnitt, för att föra in specifika webbupplevelser eller en myriad av andra möjligheter, kan vi inte vänta på att se några av de fantasifulla sätt på vilka utvecklare kommer att utnyttja Servos kraft och prestanda i Unity-byggda appar.