As ferramentas de desenvolvimento e o motor da Unidade são de longe a forma mais comum de construir aplicações para VR e AR hoje em dia. Anteriormente, nós tornamos possível exportar experiências baseadas na web a partir do Unity. Hoje, estamos animados em mostrar alguns trabalhos iniciais abordando a outra forma que os desenvolvedores da Unity querem usar a web: como um componente em seus ambientes virtuais baseados na Unity.
Building on our work porting a browser engine to many platforms and embedding scenarios, including as Firefox Reality AR for HoloLens 2, nós construímos um novo componente da Unity baseado no Servo, um moderno motor web escrito na linguagem Rust.
O motor Unity tem um sistema de plugins multiplataforma muito adaptável com um ecossistema saudável de plugins de terceiros, tanto open-source como proprietário. O sistema de plugins nos permite rodar módulos nativos do SO e conectá-los diretamente a componentes em execução no ambiente de scripts da Unity.
Os objetivos dos experimentos foram construir um plugin nativo da Unity e um conjunto de componentes de script Unity C# que permitiria a terceiros incorporar janelas do navegador Servo em cenas da Unity, e opcionalmente, fornecer suporte ao uso da superfície do navegador em aplicações VR e AR construídas na Unity.
Hoje, estamos lançando um protótipo totalmente funcional do navegador Servo rodando dentro de um plugin da Unity. Este é um olhar inicial sobre o nosso trabalho, mas sabemos que a emoção é grande para este tipo de solução, por isso esperamos que você experimente este protótipo, forneça o seu feedback e junte-se a nós na construção das coisas com ele. A versão lançada hoje tem como alvo a plataforma macOS, mas iremos adicionar algumas das outras plataformas suportadas pelo Servo muito em breve.
A começar
Abrir o plugin, em https://github.com/MozillaReality/servo-unity. Vá até lá, clique na estrela e bifurque o código, confira-o em sua máquina local e depois abra o projeto dentro da Unidade.
Instruções do desenvolvedor estão no arquivo README
no repositório.
O que ele faz
Você pode trabalhar diretamente com a janela do navegador e controles dentro do Editor da Unidade. A configuração de nível superior está no objeto ServoUnityController
. Outros objetos importantes na cena incluem o ServoUnityWindow
, ServoUnityNavbarController
, e ServoUnityMousePointer
.
O ServoUnityWindow
pode ser posicionado em qualquer lugar em uma cena de Unidade. Aqui, nós o colocamos na caverna do cogumelo Mozilla (familiar aos usuários do Firefox Reality, da incrível artista Jasmin Habezai-Fekri), e fornecemos um manipulador de câmera que nos permite mover-se pela cena e ver que é uma visão 3D do conteúdo do navegador.
Servo tem reprodução de mídia de alta qualidade através do framework GStreamer, incluindo suporte a áudio. Aqui estamos vendo um exemplo de vídeo MPEG4, rodando dentro de um build do Unity player instalado.
Pesquisa customizável está incluída no plugin. Uma grande variedade de conteúdo web pode ser visualizada com a versão atual do Servo, com maior compatibilidade web sendo trabalhada ativamente (mais sobre isso abaixo). O conteúdo WebGL também funciona.
Como funciona
Arquitectura
Desenvolvimento na Unidade usa uma arquitectura baseada em componentes, onde a Unidade executa o código do utilizador anexado a GameObject
s, organizado em cenas. Usuários customizam GameObject
s anexando scripts que executam em um ambiente C#, seja usando o compilador de tempo de execução Mono ou o IL2CPP antes do tempo. O ciclo de vida do evento Unity é acessível aos scripts do usuário herdados da classe C# da Unity MonoBehaviour
. Os scripts de usuário podem invocar código nativo em plugins (que são apenas objetos compartilhados dinâmicos nativos do SO) através do mecanismo P/Invoke do C# runtime. Na verdade, o próprio núcleo da Unidade é implementado em C++ e fornece código nativo em plugins com um segundo conjunto de interfaces acessíveis em C/C++ para auxiliar em algumas tarefas de plugins de baixo nível.
O reservatório é em si um software complexo. Por projeto, a maior parte de sua funcionalidade não voltada para o usuário é compilada em uma biblioteca Rust, libservo
. Para esta primeira fase do projeto, fazemos uso de uma interface simplificada compatível com C em outra biblioteca Rust, chamada libsimpleservo2.
Esta biblioteca expõe funções de chamada C e ganchos de retorno para controlar o navegador e visualizar sua saída. Em torno de libsimpleservo2
, nós colocamos em prática abstrações nativas em C++ que encapsulam o modelo Unity de threads e renderização, e expomos um conjunto de interfaces chamadas Unity que por sua vez são operadas pelos nossos componentes do script C#.
Configurando o conteúdo do browser em Unity
Criamos um objeto em Unity, uma instância de ServoUnityWindow
, para embrulhar uma instância da classe Unity Texture2D
e tratá-la como um painel de conteúdo do browser. Ao usar o renderizador OpenGL de Unity, a classe Texture2D
é suportada por uma textura OpenGL nativa, e passamos a textura OpenGL “name” (isto é, um ID) para o plugin, que liga a textura a um objeto framebuffer que recebe a textura composta final do Servo.
Como não temos controle sobre a ligação da textura e o contexto Unity, o design atual para atualizar esta textura usa um blit (cópia) via Servo’s surfman-chains
API. Essencialmente, o WebRender do Servo escreve em um buffer de superfície específico do SO em uma thread, e então esse buffer de superfície é encadernado somente para a thread de renderização do Unity e uma cópia da textura é feita usando as APIs OpenGL. Na implementação macOS inicial, por exemplo, o buffer de superfície é um IOSurface
que pode ser movido a custo zero entre threads, permitindo uma implementação eficiente onde o compositor do navegador pode escrever em uma thread diferente da thread que exibe a textura em Unity.
Controle e meta-dados de página são comunicados separadamente, através de um conjunto de APIs que permitem pesquisa e navegação para URLs, atualização de títulos de página, e o conjunto de botões de voltar/avançar/pararar/em casa.
Porque o conteúdo e controles do navegador são todos objetos de Unidade, a aplicação de Unidade que você está construindo pode posicionar, estilizar ou controlar programmaticamente estes de qualquer forma que você goste.
Desafios
Conseguir que o projeto chegue a este estágio não tem sido sem seus desafios, alguns dos quais ainda estamos abordando. O ambiente de scripting da Unity roda em grande parte com um único fio, com exceção das operações de renderização que ocorrem em um fio separado em uma cadência diferente. Servo, no entanto, gera potencialmente dezenas de threads de peso leve para uma variedade de tarefas. Nós tomamos o cuidado de ordenar a devolução de itens de trabalho do Servo de volta para os fios corretos na Unidade. Há ainda algumas otimizações a serem feitas para decidir quando refrescar a textura da Unidade. Atualmente, ele apenas atualiza cada frame, mas estamos adicionando uma API à interface de incorporação para permitir um controle mais fino.
Como uma incubadora para tecnologia de navegador, o Servo está focado no desenvolvimento de novas tecnologias. Uma tecnologia notável que passou do Servo para o motor Gecko que alimenta o Firefox inclui o motor de renderização baseado em GPU WebRender, e o motor CSS Stylo. Estes sucessos à parte, a compatibilidade total com a web ainda é uma área onde a Servo tem uma lacuna significativa, uma vez que nos concentramos principalmente em grandes melhorias para o utilizador e experiências específicas ao longo da longa cauda da web. Um esforço recente da comunidade Servo tem visto grandes avanços no webcompat do Servo, por isso esperamos que o subconjunto da navegação web do Servo continue a crescer rapidamente.
Planos de desenvolvimento
O apoio a toda a gama de plataformas actualmente suportadas pelo Servo é a nossa primeira prioridade de desenvolvimento de seguimento, com o Windows Win32 e o suporte Windows UWP no topo da lista. Muitos de vocês já viram a nossa aplicação Firefox Reality AR for HoloLens 2, e o suporte UWP permitir-vos-á construir o Servo numa aplicação AR própria para a plataforma HoloLens utilizando o mesmo motor de browser subjacente.
Queríamos também suportar um subconjunto maior da capacidade total do browser. No topo da lista está o suporte para múltiplas janelas. Estamos atualmente trabalhando na graduação do plugin da interface libsimpleservo2
para uma nova interface que permitirá aos aplicativos instanciar múltiplas janelas, abas e implementar recursos como histórico, favoritos e mais.
Esta primeira versão está focada na navegação web através de páginas web 2D. O Servo também suporta a web imersiva através da API WebXR, e estamos explorando a conexão do WebXR com o suporte a hardware XR da Unity através da interface de plugin. Vamos começar com o suporte para a visualização de vídeo 360°, que sabemos que da nossa base de usuários do Firefox Reality é um excelente caso de uso para o navegador.
Finalmente…
Se for um media player, uma interface dentro do jogo para a web aberta, browser-as-UI, trazendo experiências web específicas, ou a miríade de outras possibilidades, mal podemos esperar para ver algumas das maneiras imaginativas que os desenvolvedores irão explorar o poder e o desempenho do Servo dentro dos aplicativos Unity-built.