Unity中的Firefox

2020-07-25 23:18:20

Unity的开发工具和引擎无疑是当今构建VR和AR应用程序的最常用方式。以前,我们已经使从Unity导出基于网络的体验成为可能。今天,我们很兴奋地展示一些早期的工作,解决Unity开发人员想要使用网络的另一种方式:作为他们基于Unity的虚拟环境中的一个组件。

在我们将浏览器引擎移植到许多平台和嵌入场景(包括作为HoloLens 2的Firefox Reality AR)的工作基础上,我们构建了一个基于Servo的新Unity组件,Servo是一个用Rust语言编写的现代Web引擎。

Unity引擎有一个适应性很强的多平台插件系统,有一个健康的第三方插件生态系统,既有开源的,也有专有的。插件系统允许我们运行操作系统原生模块,并将它们直接连接到Unity脚本环境中执行的组件。

这些实验的目标是构建一个Unity原生插件和一组Unity C#脚本组件,允许第三方将Servo浏览器窗口合并到Unity场景中,并可选地支持在Unity内置的VR和AR应用程序中使用浏览器界面。

今天,我们将发布一个运行在Unity插件中的Servo网络浏览器的全功能原型。这是对我们工作的早期展望,但我们知道这种解决方案非常令人兴奋,所以我们希望您尝试此原型,提供您的反馈,并与我们一起使用它来构建东西。今天发布的版本针对的是MacOS平台,但我们很快会添加一些Servo支持的其他平台。

我们已经在https://github.com/MozillaReality/servo-unity.上开源了这个插件。直接过去,单击星号并分叉代码,将其签出到您的本地计算机,然后在Unity中打开该项目。

可以直接使用浏览器窗口和Unity编辑器中的控件。顶级配置位于ServoUnityController对象上。场景中的其他重要对象包括ServoUnityWindow、ServoUnityNavbarController和ServoUnityMousePointer。

ServoUnityWindow可以位于Unity场景中的任何位置。在这里,我们将其放入Mozilla蘑菇洞(Firefox Reality的用户熟悉,由令人惊叹的艺术家Jasmin Habezai-Fekri创作),并提供了一个相机操纵器,允许我们在场景中移动,并看到它是浏览器内容的3D视图。

伺服通过GStreamer框架提供高质量的媒体播放,包括音频支持。这里我们正在观看示例MPEG4视频,在部署的Unity player内部运行。

插件中包含可自定义的搜索。当前版本的Servo可以查看各种各样的Web内容,并且正在积极研究更好的Web兼容性(更多信息见下文)。WebGL内容也可以使用。

Unity中的开发使用基于组件的架构,在这种架构中,Unity执行附加到游戏对象上的用户代码,这些代码被组织到场景中。用户通过附加在C#环境中执行的脚本(使用Mono运行时或IL2CPP预编译器)来自定义游戏对象。从Unity C#类MonoBehaviour继承的用户脚本可以访问Unity事件生命周期。用户脚本可以通过C#运行时的P/Invoke机制调用插件(它们只是操作系统本地的动态共享对象)中的本机代码。事实上,Unity的核心本身是用C++实现的,并在插件中提供本机代码和第二组C/C++可访问的接口,以帮助完成一些低级插件任务。

伺服本身就是一款复杂的软件。根据设计,它的大部分非面向用户的功能都编译成一个Rust库,名为libserver.。对于该项目的第一阶段,我们使用另一个名为libsimpleservo2的Rust库中与C兼容的简化接口。此库公开C可调用函数和回调挂钩,以控制浏览器并查看其输出。围绕libsimpleservo2,我们放置了本地C++抽象,这些抽象封装了线程和呈现的Unity模型,并公开了一组Unity可调用的接口,这些接口依次由我们的C#脚本组件操作。

我们在Unity(ServoUnityWindow的实例)中创建一个对象,以包装Unity的Texture2D类的实例,并将其视为浏览器内容窗格。使用Unity的OpenGL渲染器时,Texture2D类由本地OpenGL纹理支持,我们将OpenGL纹理“name”(即ID)传递给插件,该插件将纹理绑定到从Servo接收最终合成纹理的帧缓冲区对象。

由于我们无法控制纹理和Unity上下文的绑定,当前用于更新此纹理的设计通过Servo的Surfman-Chains API使用Blit(复制)。本质上,Servo的WebRender在一个线程上写入特定于操作系统的表面缓冲区,然后将该表面缓冲区以只读方式绑定到Unity的渲染线程,并使用OpenGLAPI创建纹理副本。例如,在最初的MacOS实现中,表面缓冲区是可以在线程之间零成本移动的IOSurface,从而实现了一种高效的实现,其中浏览器合成器可以向Unity中显示纹理的线程写入不同的线程。

控制和页面元数据通过一组允许搜索和导航到URL、更新页面标题和常见的后退/前进/停止/主页按钮集的API分开通信。

因为浏览器内容和控件最终都是Unity对象,所以您正在构建的Unity应用程序可以以您喜欢的任何方式定位、设置样式或以编程方式控制它们。

让项目发展到这个阶段并不是没有挑战,我们仍在解决其中一些挑战。Unity的脚本环境在很大程度上是单线程运行的,除了在不同节奏的单独线程上进行的呈现操作。然而,伺服可能会为各种任务产生数十个轻量级线程。我们已经注意将从Servo返回的工作项编排回Unity中的正确线程。在决定何时刷新Unity纹理时,还有一些剩余的优化需要进行。目前,它只刷新每一帧,但我们正在向嵌入接口添加一个API,以允许更细粒度的控制。

作为浏览器技术的孵化器,Servo专注于开发新技术。从Servo转移到支持Firefox的Gecko引擎的值得注意的技术包括基于GPU的渲染引擎WebRender和CSS引擎Stylo。撇开这些成功不谈,完全的网络兼容性仍然是Servo有很大差距的领域,因为我们主要关注用户的重大改进和网络长尾的具体体验。Servo社区最近的一项努力看到了Servo的Webcompat取得了巨大的进步,因此我们预计Servo可浏览的Web子集将继续快速增长。

支持Servo目前支持的所有平台是我们后续开发的首要任务,其中Windows Win32和Windows UWP支持位居首位。你们中的许多人都看过我们的Firefox Reality AR for HoloLens 2应用程序,UWP支持将允许您使用相同的底层浏览器引擎将Servo构建到您自己的用于HoloLens平台的AR应用程序中。

我们还希望支持完整浏览器功能的更大子集。首当其冲的是多窗口支持。我们目前正致力于将插件从libsimpleservo2界面升级到一个新的界面,该界面将允许应用程序实例化多个窗口、标签,并实现历史记录、书签等功能。

这第一个版本侧重于可通过2D网页浏览的Web。Serve还通过WebXR API支持沉浸式Web,我们正在探索通过插件接口将WebXR连接到Unity的XR硬件支持。我们将从支持观看360°视频开始,我们从Firefox Reality用户群中了解到,这是浏览器的主要使用案例。

无论是媒体播放器,开放网络的游戏界面,浏览器即用户界面,带来特定的网络体验,还是无数其他的可能性,我们都迫不及待地想看到开发人员将在Unity构建的应用程序中利用Servo的能力和性能的一些富有想象力的方式。