Un plugin per browser per Unity

Gli strumenti di sviluppo e il motore di Unity sono di gran lunga il modo più comune per costruire applicazioni per VR e AR oggi. In precedenza, abbiamo reso possibile l’esportazione di esperienze basate sul web da Unity. Oggi, siamo entusiasti di mostrare alcuni primi lavori che affrontano l’altro modo in cui gli sviluppatori di Unity vogliono usare il web: come componente nei loro ambienti virtuali basati su Unity.

Sulla base del nostro lavoro di porting di un motore browser a molte piattaforme e scenari di embedding, compreso Firefox Reality AR per HoloLens 2, abbiamo costruito un nuovo componente Unity basato su Servo, un moderno motore web scritto nel linguaggio Rust.

Il motore Unity ha un sistema di plugin multipiattaforma molto adattabile con un sano ecosistema di plugin di terze parti, sia open-source che proprietari. Il sistema di plugin ci permette di eseguire moduli nativi del sistema operativo e di collegarli direttamente ai componenti in esecuzione nell’ambiente di scripting Unity.

Gli obiettivi degli esperimenti erano di costruire un plugin nativo di Unity e un insieme di componenti di script Unity C# che avrebbero permesso a terzi di incorporare le finestre del browser Servo nelle scene di Unity e, opzionalmente, fornire supporto per l’utilizzo della superficie del browser nelle app VR e AR costruite in Unity.

Oggi, stiamo rilasciando un prototipo completamente funzionante del browser web Servo che gira all’interno di un plugin Unity. Questo è uno sguardo iniziale al nostro lavoro, ma sappiamo che l’eccitazione è alta per questo tipo di soluzione, quindi speriamo che proverete questo prototipo, fornirete il vostro feedback e vi unirete a noi per costruire cose con esso. La versione rilasciata oggi si rivolge alla piattaforma macOS, ma aggiungeremo alcune delle altre piattaforme supportate da Servo molto presto.

Iniziare

Abbiamo reso open-source il plugin, a https://github.com/MozillaReality/servo-unity. Andate lì, cliccate sulla stella e fate un fork del codice, fatelo sulla vostra macchina locale e poi aprite il progetto in Unity.

Le istruzioni per lo sviluppatore sono nel file README nel repository.

Cosa fa

Puoi lavorare direttamente con la finestra del browser e i controlli all’interno dell’editor di Unity. La configurazione di primo livello è sull’oggetto ServoUnityController. Altri oggetti importanti nella scena sono ServoUnityWindow, ServoUnityNavbarController e ServoUnityMousePointer.

Il ServoUnityWindow può essere posizionato ovunque in una scena Unity. Qui, l’abbiamo fatto cadere nella caverna del fungo di Mozilla (familiare agli utenti di Firefox Reality, dall’incredibile artista Jasmin Habezai-Fekri), e abbiamo fornito un manipolatore di telecamera che ci permette di muoverci intorno alla scena e vedere che è una vista 3D del contenuto del browser.

Servo ha una riproduzione di alta qualità dei media tramite il framework GStreamer, incluso il supporto audio. Qui stiamo visualizzando un video MPEG4 di esempio, in esecuzione all’interno di un player Unity distribuito.

La ricerca personalizzabile è inclusa nel plugin. Un’ampia varietà di contenuti web è visualizzabile con l’attuale versione di Servo, con una maggiore compatibilità web su cui si sta lavorando attivamente (maggiori informazioni in seguito). Funziona anche il contenuto WebGL.

Come funziona

Architettura

Lo sviluppo in Unity usa un’architettura basata sui componenti, dove Unity esegue il codice utente collegato ai GameObject, organizzati in scene. Gli utenti personalizzano i GameObject allegando degli script che vengono eseguiti in un ambiente C#, utilizzando il runtime Mono o il compilatore IL2CPP ahead-of-time. Il ciclo di vita degli eventi di Unity è accessibile agli script utente che ereditano dalla classe Unity C# MonoBehaviour. Gli script utente possono invocare il codice nativo nei plugin (che sono solo oggetti condivisi dinamici OS-nativi) attraverso il meccanismo P/Invoke del runtime C#. Infatti, il nucleo stesso di Unity è implementato in C++ e fornisce al codice nativo nei plugin una seconda serie di interfacce accessibili in C/C++ per assistere in alcuni compiti di basso livello dei plugin.

Servo stesso è un software complesso. Per progettazione, la maggior parte delle sue funzionalità non rivolte all’utente sono compilate in una libreria Rust, libservo. Per questa prima fase del progetto, facciamo uso di un’interfaccia semplificata compatibile con C in un’altra libreria Rust chiamata libsimpleservo2. Questa libreria espone funzioni richiamabili in C e ganci di callback per controllare il browser e visualizzare il suo output. Intorno a libsimpleservo2, abbiamo messo in atto astrazioni native C++ che incapsulano il modello Unity di thread e rendering, ed espongono un insieme di interfacce richiamabili da Unity che sono a loro volta gestite dai nostri componenti di script C#.

Il contenuto del browser in Unity

Creiamo un oggetto in Unity, un’istanza di ServoUnityWindow, per avvolgere un’istanza della classe Texture2D di Unity e trattarla come un pannello del contenuto del browser. Quando si usa il renderer OpenGL di Unity, la classe Texture2D è supportata da una texture OpenGL nativa, e noi passiamo il “nome” della texture OpenGL (cioè un ID) al plugin, che lega la texture a un oggetto framebuffer che riceve la texture finale composta da Servo.

Poiché non abbiamo il controllo sul legame tra la texture e il contesto di Unity, il design attuale per l’aggiornamento di questa texture utilizza un blit (copia) tramite l’API surfman-chains di Servo. Essenzialmente, il WebRender di Servo scrive su un buffer di superficie specifico del sistema operativo su un thread, e poi questo buffer di superficie è legato in sola lettura al thread di rendering di Unity e una copia della texture viene fatta usando le API OpenGL. Nell’implementazione iniziale di macOS, per esempio, il surface buffer è un IOSurface che può essere spostato a costo zero tra i thread, permettendo un’implementazione efficiente in cui il compositore del browser può scrivere in un thread diverso da quello che visualizza la texture in Unity.

I meta-dati di controllo e di pagina sono comunicati separatamente, attraverso un insieme di API che permettono la ricerca e la navigazione verso gli URL, l’aggiornamento dei titoli delle pagine, e il solito set di pulsanti back/forward/stop/home.

Perché il contenuto e i controlli del browser sono tutti oggetti Unity, l’applicazione Unity che stai costruendo può posizionarli, stilizzarli o controllarli programmaticamente in qualsiasi modo tu voglia.

Sfide

Per portare il progetto a questo stadio non sono mancate le sfide, alcune delle quali sono ancora da affrontare. L’ambiente di scripting di Unity funziona in gran parte a thread singolo, con l’eccezione delle operazioni di rendering che avvengono su un thread separato con una cadenza diversa. Servo, tuttavia, genera potenzialmente decine di thread leggeri per una varietà di compiti. Abbiamo fatto attenzione a smistare gli elementi di lavoro di ritorno da Servo ai thread corretti in Unity. Ci sono ancora alcune ottimizzazioni da fare nel decidere quando aggiornare la texture di Unity. Attualmente, si aggiorna solo ogni fotogramma, ma stiamo aggiungendo un’API all’interfaccia di incorporamento per permettere un controllo più fine.

Come incubatore per la tecnologia dei browser, Servo è concentrato sullo sviluppo di nuove tecnologie. La tecnologia notevole che è passata da Servo al motore Gecko che alimenta Firefox include il motore di rendering basato su GPU WebRender e il motore CSS Stylo. A parte questi successi, la piena compatibilità con il web è ancora un’area in cui Servo ha un gap significativo, dato che ci siamo concentrati principalmente su grandi miglioramenti per l’utente ed esperienze specifiche sulla lunga coda del web. Un recente sforzo da parte della comunità di Servo ha visto grandi progressi nel webcompat di Servo, quindi ci aspettiamo che il sottoinsieme del web navigabile da Servo continui a crescere rapidamente.

Piani di sviluppo

Supportare l’intera gamma di piattaforme attualmente supportate da Servo è la nostra prima priorità di sviluppo successiva, con il supporto Windows Win32 e Windows UWP in cima alla lista. Molti di voi hanno visto la nostra app Firefox Reality AR per HoloLens 2, e il supporto UWP vi permetterà di costruire Servo in una vostra app AR per la piattaforma HoloLens usando lo stesso motore di base del browser.

Vorremmo anche supportare un sottoinsieme maggiore delle capacità complete del browser. In cima alla lista c’è il supporto per finestre multiple. Stiamo attualmente lavorando per graduare il plugin dall’interfaccia libsimpleservo2 a una nuova interfaccia che permetterà alle applicazioni di istanziare finestre multiple, schede e implementare caratteristiche come la cronologia, i segnalibri e altro.

Questa prima release è focalizzata sul web navigabile attraverso pagine web 2D. Servo supporta anche il web immersivo attraverso l’API WebXR, e stiamo esplorando il collegamento di WebXR al supporto hardware XR di Unity attraverso l’interfaccia dei plugin. Inizieremo con il supporto per la visualizzazione di video a 360°, che sappiamo dalla nostra base di utenti di Firefox Reality essere un caso d’uso primario per il browser.

Finalmente…

Che si tratti di un lettore multimediale, un’interfaccia in-game per il web aperto, browser-as-UI, portando esperienze web specifiche, o la miriade di altre possibilità, non vediamo l’ora di vedere alcuni dei modi fantasiosi in cui gli sviluppatori sfrutteranno la potenza e le prestazioni di Servo all’interno delle app costruite con Unity.