Et browser-plugin til Unity

Unitys udviklingsværktøjer og -motor er langt den mest almindelige måde at bygge applikationer til VR og AR på i dag. Tidligere har vi gjort det muligt at eksportere webbaserede oplevelser fra Unity. I dag glæder vi os til at vise noget tidligt arbejde, der tager fat på den anden måde, som Unity-udviklere ønsker at bruge internettet på: som en komponent i deres Unity-baserede virtuelle miljøer.

Med udgangspunkt i vores arbejde med at portere en browsermotor til mange platforme og indlejringsscenarier, herunder som Firefox Reality AR til HoloLens 2, har vi bygget en ny Unity-komponent baseret på Servo, en moderne webmotor, der er skrevet i Rust-sproget.

Unity-motoren har et meget tilpasningsdygtigt plugin-system til flere platforme med et sundt økosystem af plugins fra tredjeparter, både open source og proprietære plugins. Pluginsystemet giver os mulighed for at køre OS-native moduler og forbinde dem direkte med komponenter, der udføres i Unity-scriptingmiljøet.

Målene med eksperimenterne var at opbygge et Unity-nativt plugin og et sæt Unity C#-scriptkomponenter, der ville gøre det muligt for tredjeparter at inkorporere Servo-browservinduer i Unity-scener og eventuelt give støtte til brug af browseroverfladen i VR- og AR-apps, der er bygget i Unity.

I dag frigiver vi en fuldt funktionsdygtig prototype af Servo-webbrowseren, der kører i et Unity-plugin. Dette er et tidligt indblik i vores arbejde, men vi ved, at begejstringen er stor for denne form for løsning, så vi håber, at du vil prøve denne prototype, give os din feedback og være med til at bygge ting med den. Den version, der er udgivet i dag, er rettet mod macOS-platformen, men vi vil meget snart tilføje nogle af de andre platforme, der understøttes af Servo.

Gå i gang

Vi har open-sourcet plugin’et, på https://github.com/MozillaReality/servo-unity. Gå over, klik på stjernen og fork koden, tjek den ud på din lokale maskine, og åbn derefter projektet i Unity.

Instruktioner til udviklere findes i README-filen i repositoryet.

Hvad det gør

Du kan arbejde direkte med browservinduet og kontrolelementerne inde i Unity-editoren. Konfigurationen på øverste niveau er på ServoUnityController-objektet. Andre vigtige objekter i scenen omfatter ServoUnityWindow, ServoUnityNavbarController og ServoUnityMousePointer.

Den ServoUnityWindow kan placeres hvor som helst i en Unity-scene. Her har vi smidt den i Mozilla-svampegrotten (kendt af brugere af Firefox Reality, af den fantastiske kunstner Jasmin Habezai-Fekri), og vi har leveret en kameramanipulator, der gør det muligt at bevæge sig rundt i scenen og se, at det er en 3D-visning af browserens indhold.

Servo har medieafspilning i høj kvalitet via GStreamer-rammen, herunder lydunderstøttelse. Her ser vi et eksempel på MPEG4-video, der kører inde i et implementeret Unity-afspiller-build.

Søgning, der kan tilpasses, er inkluderet i plugin’et. En bred vifte af webindhold kan vises med den nuværende version af Servo, og der arbejdes aktivt på større webkompatibilitet (mere om det nedenfor). WebGL-indhold fungerer også.

Sådan fungerer det

Arkitektur

Udviklingen i Unity bruger en komponentbaseret arkitektur, hvor Unity udfører brugerkode knyttet til GameObjects, organiseret i scener. Brugerne tilpasser GameObjects ved at vedhæfte scripts, der udføres i et C#-miljø, enten ved hjælp af Mono runtime eller IL2CPP ahead-of-time compiler. Unity-hændelseslivscyklusen er tilgængelig for brugerscripts, der arver fra Unity C#-klassen MonoBehaviour. Brugerscripts kan påkalde indfødt kode i plugins (som blot er OS-native dynamiske delte objekter) via C#-køringstidens P/Invoke-mekanisme. Faktisk er Unitys kerne selv implementeret i C++ og giver indfødt kode i plugins et andet sæt C/C++-tilgængelige grænseflader til at hjælpe med nogle lavniveauopgaver for plugins.

Servo er i sig selv et komplekst stykke software. Det er designet således, at de fleste af de funktioner, der ikke er rettet mod brugeren, er kompileret i et Rust-bibliotek, libservo. I denne første fase af projektet gør vi brug af en forenklet C-kompatibel grænseflade i et andet Rust-bibliotek ved navn libsimpleservo2. Dette bibliotek udsætter C-kaldbare funktioner og callback-kroge til at styre browseren og se dens output. Omkring libsimpleservo2 indfører vi native C++-abstraktioner, der indkapsler Unity-modellen for tråde og rendering og eksponerer et Unity-kaldbart sæt grænseflader, der igen betjenes af vores C#-scriptkomponenter.

Indførelse af browserindholdet i Unity

Vi opretter et objekt i Unity, en instans af ServoUnityWindow, for at indpakke en instans af Unitys Texture2D-klasse og behandle den som en browserindholdsrude. Når vi bruger Unitys OpenGL-renderer, understøttes Texture2D-klassen af en indfødt OpenGL-tekstur, og vi sender OpenGL-teksturens “navn” (dvs. et ID) til plugin’et, som binder tekstur til et framebuffer-objekt, der modtager den endelige sammensatte tekstur fra Servo.

Da vi ikke har kontrol over bindingen af tekstur og Unity-konteksten, bruger det nuværende design til opdatering af denne tekstur en blit (kopi) via Servos surfman-chains API. I det væsentlige skriver Servos WebRender til en OS-specifik overfladebuffer på én tråd, hvorefter denne overfladebuffer bindes skrivebeskyttet til Unitys rendertråd, og der laves en teksturkopi ved hjælp af OpenGL-API’er. I den oprindelige macOS-implementering er overfladebufferen f.eks. en , som kan flyttes mellem tråde uden omkostninger, hvilket giver mulighed for en effektiv implementering, hvor browserkompositoren kan skrive i en anden tråd end den tråd, der viser tekstur i Unity.

Kontrol- og side-metadata kommunikeres separat via et sæt API’er, der muliggør søgning og navigation til URL’er, opdatering af sidetitler og det sædvanlige sæt af back/forward/stop/home-knapper.

Da browserens indhold og kontroller i sidste ende alle er Unity-objekter, kan den Unity-applikation, du bygger, placere, style eller programmatisk styre disse på en hvilken som helst måde.

Udfordringer

Det har ikke været uden udfordringer at få projektet frem til dette stadie, og nogle af dem er vi stadig i gang med at løse. Unitys scriptingmiljø kører stort set single-threaded, med undtagelse af renderingsoperationer, som foregår på en separat tråd i en anden kadence. Servo spawner imidlertid potentielt snesevis af lette tråde til en række forskellige opgaver. Vi har sørget for at samle tilbagevendende arbejdsemner fra Servo tilbage til de korrekte tråde i Unity. Der er nogle resterende optimeringer, der skal foretages med hensyn til at beslutte, hvornår Unity-teksturene skal opdateres. I øjeblikket opdateres den bare hver frame, men vi er ved at tilføje et API til indlejringsgrænsefladen for at muliggøre en mere finkornet styring.

Som inkubator for browserteknologi er Servo fokuseret på at udvikle nye teknologier. Bemærkelsesværdig teknologi, der er flyttet fra Servo til Gecko-motoren, der driver Firefox, omfatter den GPU-baserede renderingsmotor WebRender og CSS-motoren Stylo. Bortset fra disse succeser er fuld webkompatibilitet stadig et område, hvor Servo har et betydeligt efterslæb, da vi primært har fokuseret på store forbedringer for brugeren og specifikke oplevelser over den lange hale af internettet. En nylig indsats fra Servo-fællesskabet har givet store fremskridt i Servos webkompatibilitet, så vi forventer, at den delmængde af internettet, der kan gennemses af Servo, fortsat vil vokse hurtigt.

Udviklingsplaner

Understøttelse af hele rækken af platforme, der i øjeblikket understøttes af Servo, er vores første opfølgende udviklingsprioritet, med Windows Win32- og Windows UWP-understøttelse øverst på listen. Mange af jer har set vores Firefox Reality AR for HoloLens 2-app, og UWP-understøttelse vil give jer mulighed for at bygge Servo ind i en jeres egne AR-apps til HoloLens-platformen ved hjælp af den samme underliggende browsermotor.

Vi vil også gerne understøtte en større delmængde af den fulde browserfunktionalitet. Højt på listen står understøttelse af flere vinduer. Vi arbejder i øjeblikket på at graduere plugin’et fra libsimpleservo2-grænsefladen til en ny grænseflade, der vil gøre det muligt for programmer at instantiere flere vinduer, faner og implementere funktioner som historik, bogmærker og meget mere.

Denne første udgivelse er fokuseret på web, der kan gennemses via 2D-websider. Servo understøtter også det fordybende web gennem WebXR API’et, og vi er ved at undersøge mulighederne for at forbinde WebXR med Unitys XR-hardwareunderstøttelse gennem plugin-interfacet. Vi starter med understøttelse af visning af 360°-video, som vi ved fra vores Firefox Reality-brugerbase er et af de vigtigste anvendelsesområder for browseren.

Endeligt…

Hvad enten det er en medieafspiller, en grænseflade i spil til det åbne web, browser som brugergrænseflade, inddragelse af specifikke weboplevelser eller et utal af andre muligheder, kan vi ikke vente med at se nogle af de fantasifulde måder, hvorpå udviklere vil udnytte Servos kraft og ydeevne i Unity-byggede apps.