什么是 Unity WebGL?**
WebGL工程选项允许Unity以JavaScript程序形式发布使用HTMl5技术和WebGL渲染API、在网页浏览器中运行的Unity内容。为了构建和测试WebGL内容,在“Build Player”窗口中选择WebGL构建目标,并且点击“Build & Run ”。
技术概览
为了在WebGL中运行,所有代码需要是JavaScript。我们使用 emscripten 编译器工具链来交叉编译Unity运行时代码(用C和C++编写)到asm.js的JavaScript代码。asm.js是一个非常理想的JavaScript子集,允许JavaScript引擎 预编译asm.js代码为极具性能的原生代码。
为了转换.NET 游戏代码(C#和UnityScript脚本)至JavaScript,我们使用了一个称为IL2CPP的技术。IL2CPP获取.NET字节代码并将它转换为对应的C++源文件,然后通过使用emscripten,这些源文件被编译,最终将用户的脚本转换为JavaScript。
平台支持
Unity WebGL内容在当前大部分桌面主流浏览器都支持,然而不同的浏览器,提供的支持程度仍有所差别。移动设备并不被Unity WebGL支持。
不是所有Unity特性在WebGL工程中都可用,大部分是因为平台限制的关系,例如:
Unity WebGL在一定程度上支持所有的桌面主流浏览器。然而,不同的浏览器之间,支持程度、预期性能并不一样。请通过以下的表格,对Unity WebGL特性,以及哪些浏览器支持它们做一个整体查看。
注意,Unity WebGL 内容目前在移动设备上不支持。它或许在高档设备仍可以工作,但许多现有的设备并不足够强大,且没有足够的内存空间来很好地支持Unity WebGL内容。出于这个原因,当尝试在移动设备的浏览器上加载内容时,Unity WebGL会显示一个警告信息(如果需要,此功能可以被关闭)。
注意到,这个兼容表针对浏览器特定版本才有意义。更高版本会继续支持,但先前的版本可能会不稳定。
Mozilla Firefox 42 | Google Chrome 46 | Apple Safari 9.0 | MS Internet Explorer 11 | MS Edge 13 | |
WebGL支持 | 是。GPU黑名单可用。WebGL可能不被一些特定的老显卡所支持。 | 是。GPU黑名单可用。WebGL可能不被一些特定的老显卡所支持。 | 是。需要Safari8以及更高版本。 | 是。需要IE11及更高版本。 | 是 |
网页音效。网页音效API被用于在Unity WebGL内容中播放声音。 | 是 | 是 | 是 | 否 | 是 |
全屏 | 是 | 是 | 否。Safari supports the HTML5 full-screen API, but no keyboard input when in full-screen mode, so Unity will disable full-screen functionality when running in Safari.Safari支持HTML5全屏API,但在全屏模式下没有键盘输入。所以在Safari中运行时,Unity将关闭全屏功能。 | 是 | 是 |
游标锁定 | 是 | 是 | 否 | 否 | 是。需要Edge13及更高版本。 |
手柄 | 是 | 是 | 否 | 否 | 是 |
本地索引数据库 | 是。火狐直到42版、以及Safari不支持用于在一个iFrame中运行内容的索引数据库。火狐43及以后的版本会修复此支持。 | 是 | 是。火狐直到42版、以及Safari不支持用于在一个iFrame中运行内容的索引数据库。火狐43及以后的版本会修复此支持。 | 是 | 是 |
网络套接字 | 是 | 是 | 是 | 是 | 是 |
网络实时通信 | 是 | 是 | 否 | 否 | 是 |
WebGL2.0 | 否。火狐支持WebGL2.0,但默认不可用,并且需要在about:config中开启。 | 否 | 否 | 否 | 否。Chrome支持WebGL2.0,但默认不可用,并且需要在chrome://flags中开启。 |
asm.js预编译。asm.js是浏览器可以针对性优化的JavaScript子集。由于Unity使用asm.js,所以实现了asm.js支持的浏览器能够更快地运行Unity WebGL。 | 是 | 否 | 否 | 否 | 是 |
注意
Chrome可能需要大量的内存来解析生成的JavaScript代码,可能在32位浏览器重加载内容时,引起内存溢出或崩溃错误。查看“Memory Considerations”(暂未译出)获得更多关于内存使用的信息。
Internet Explorer 不支持音效,并且太缓慢而无法像样地支持大部分Unity WebGL内容。出于这个原因,当在IE中打开内容时,我们将展示一个关于使用不支持的浏览器的警告信息。在表格中列举IE只是为了完整性;应当建议IE使用者升级到微软新的Edge浏览器。
当你构建一个WebGL项目时,Unity用以下文件创建了一个文件夹:
开发/发行 文件夹包含了以下文件(“MyProject”文件名称代表你项目的名称)。(注意,如果你生成一个发行版工程,这个文件夹里的文件会诶压缩并有一个.gz的后缀。查看下面分发尺寸的注释。)
你可以通过用大部分浏览器打开index.html文件,直接查看你的WebGL 播放器。然而,出于安全的原因,Chrome在从本地文件URL中打开的脚本上做了限制,所以这个技术在Chrome中无法使用。为了绕过Chrome的限制,使用Unity的Build&Run命令(File->Build&Run);这个文件就暂时在一个本地网页服务器中,并且是从一个本地宿主URL中打开。或者,可以用 –disable-web-security 命令行选项来运行Chrome,这允许Chrome从本地文件的URL加载内容。
在一些服务器上,用户需要生成可读取的.mem和.data文件,因为服务器需要提供这些文件给用户。
构建播放器选项
(菜单:File->Build Settings…)进入WebGL选项对话框。在对话框中,从平台列表中选择WebGL,然后选择播放器选项…
开发工程
当你选中Development Build 勾选框,Unity生成一个开发工程,有事件探查器支持喝一个开发控制台来查看错误。另外,开发工程不压缩内容(即,内容不是最小化的);维持在在可以人工阅读的JavaScript形式,保留了函数名,这样用户得到有用的错误追踪栈。注意,这意味着开发工程会非常大,太大而无法发布。
使用预构建引擎
这个选项仅在用户勾选了开发工程时出现。在工程选项对话框中使用“Use pre-build Engine”选项来在开发期间加速构建迭代时间。当此选项被启用时,Unity仅重构建”manager code”,动态链接到预编译Unity引擎,这样项目的重构建大概会快30%至40%。注意,这种构建类型仅适合于开发目的,因为总是产生”unstripped”引擎代码。此外,由于动态链接,这种工程的类型比普通类型的执行上更慢。
自动连接探查器
此选项仅当用户勾选了开发工程时可用。勾选自动连接探查器选项,让用户探查Unity WebGL内容。对于WebGL,它不可能连接到事件探查器来运行工程像在其它平台上那样,所以用户需要使用这个选项来连接内容到编辑器。这是因为事件探查器连接通过使用WebGL的WebSockets被掌控,单一个网页浏览器仅允许内容的向外连接。
播放器设置
WebGL在播放器设置的检视器窗口(菜单:Edit->Project Settings ->Player)中,有一些另外的选项。
其它选项 Other Settings
精简引擎代码
打开 Other Settings 来选择 Strip Engine Code选项。这个选项默认被选中,来允许代码为WebGL所精简。随着这个选项被选中,Unity不包括任何你不使用的类的代码。例如,如果你不使用任何物理组件或功能,那么整个物理引擎会被从你的工程中移除。查看下方的精简区来获得更多细节。
发布选项
WebGL内存大小
打开Publishing Settings进入WebGL 内存大小区域。这里,你可以指定内容应为它的堆分配多少内存(以MB为单位)。如果这个值太低,用户会收到“内存溢出”错误。这意味着要加载的内容喝场景无法完整放入可用的内存中。然而如果这个值太高,内容可能无法加载到一些浏览器或一些机器里,因为浏览器可能没有足够的可用内存来分配要求的堆尺寸。这个值被写到在生成的 .html 文件里一个名为TOTAL_MEMORY的变量中,所以如果用户希望尝试这个值,可以编辑 .html 文件来避免重构你的项目。查看在 WebGL memory usage 中的 User Manual 页面来获取更多细节。
启用异常
打开发布设置来进入 Enable Exceptions(启用异常) 。启用异常允许用户指定在运行时意外的代码行为(通常被认为是错误)如何被处理。这里有三个选项:
Unity通过在代码中嵌入检查,为它们生成这些异常;因此这些选项增大了代码尺寸并且降低了性能。仅在需要调试时,在代码中使用这个模式,因为它构建了非常庞大且非常缓慢的工程。
选择Publishing Settings(发布设置)来进入Data Caching(数据缓存)。选择此项来开启播放器数据的自动本地缓存。这个选项设置资源在浏览器的索引型数据库中,作为本地的缓存而存储;这样在内容的后续运行时,资源不会被再次下载。注意,不同的浏览器在允许索引型数据库存储时,有不同的规则;浏览器可能询问用户来允许存储数据,并且工程可能超出被浏览器定义的尺寸限制。
发行大小
当向WebGL平台发布时,保证工程的大小尽可能低,让用户在内容开始前,只经历可忍受的下载时长。关于降低资源尺寸的通用技巧,请阅读Reducing the file size of the build。
对于WebGL的专有提示
如果要生成一个发行版工程,Unity根据在WebGL PlayerSetings->Publishing Settings窗口中选择的Compression Format(压缩格式),来压缩工程输出文件。
查看Deploying compressed builds中的文档,来获取更多这些选项的信息,以及如何用这些选项来发布工程。
资源包
因为所有资源数据需要在内容之前预先下载,所以你应当考虑从你的主数据文件中移除资源,放入资源包中。用这种方式,你可以为你的内容创建一个能迅速读取的,小的加载场景。资源包也有助于资源数据内存管理:你可以通过调用AssetBundle.Unload,从内存中卸载你不再需要的资源数据。
一些在WebGL平台上使用资源包时需要考虑的事情:
当你在资源包中使用在你主工程中没用到的类类型,Unity会对这些类从工程中精简掉这些代码。当尝试从资源包中加载资源时,这可能引发错误。查看在下方 Stripping 中的部分,来学习如何修复这个问题。
WebGL不支持多线程,但http下载仅在它们结束下载时可用。由于这个原因,当下载完成时,Unity WebGL工程需要在主线程中解压资源数据,阻塞了主线程。为了避免这一中断,对于在WebGL上的资源包,LZMA AssetBundle compression是不可用的。资源包换成用LZ4来压缩,在解压缩时非常迅速。如果你需要比LZ4更小的压缩尺寸,你可以配置你的网页服务器对你的资源包使用gzip或者Brotli压缩(比LZ4压缩更小)。查看Deploying compressed builds中的文档来获取如何进行压缩的更多信息。
通过使用浏览器的索引型数据库API,来实现:在WebGL中使用 WWW.LoadFromCacheOrDownload 以支持资源包在用户的电脑上缓存。注意,索引型数据库可能在某些浏览器上支持有限,且这些浏览器可能要求用户提供在磁盘上存储数据的权限。查看 WebGL browser compatibility 中的文档来获取更多信息。
Stripping 精简
Unity 默认会从你的工程中移除所有不被使用的代码。可以通过播放器设定检视器窗口来改变设置。(菜单:Edit->Project Settings->Player):选择Other Settings 进入Strip Engine Code 精简代码选项。开启精简选项会更好。
选择精简,Unity对你的项目中任何被使用的UnityObject派生类进行检查(无论是被脚本代码引用,或是在你场景序列化数据中)。然后,从工程中移除没有任何类被使用的Unity子系统。这让你的工程代码更少,需要下载与解析的量都更少(所以代码运行更快,使用更少的内存)。
**代码精简带来的问题**Issues with code stripping
如果精简了实际上必须保留的代码,可能导致你的项目出问题。当你在运行时,要加载的资源包中原本包含不在主工程中、并已被精简了的类,就会产生问题。当这发生时,浏览器的JavaScript控制台会出现错误信息(并可能伴随着更多错误)。例如: 无法生成编号为XXX的类
为了排除这些从无,在类编号引用中查找,以查看是哪个类在尝试创建实例。在这种情况下,你可以强制要求Unity在工程中为这个类包含代码,要么通过在你的脚本或场景中添加一个对该类的引用,或者对你的项目增加一个link.xml文件。
下面是一个确保碰撞器类(以及物理模块)在项目中得以保留的例子。向名为link.xml的文件中添加这些XML代码,并将此文件放到你的资源文件夹中。
如果你怀疑,精简引起你工程的问题,你也可以尝试在测试期间关闭精简引擎代码选项。
Unity不提供查看哪些模块和类在工程中包含的方便途径,这途径可以让你最优化地精简项目。然而,为了得到所包含类及模块的概览,你在生成一个工程后,可以查看生成的文件Temp/StagingArea/Data/il2cppOutput/UnityClassRegistration.cpp 。
注意,精简引擎代码选项只影响Unity引擎代码。IL2CPP总是从你管理的dll和脚本精简字节代码。当你需要在你的代码中,通过反射动态地引用管理的类、而不是通过静态引用,这会引起问题。如果你需要通过反射存取类型,你也需要设置一个link.xml文件来保留这些类。查看iOS Build size optimization 的文档来获取更多link.xml文件的信息。
移动工程输出文件
如果你希望改变你输出文件相对于index.html文件的位置,可以通过编辑dataUrl
,codeUrl,以及memUrl区,以及在index.html文件中的UnityLoader.js脚本标签来实现。你可以为这些内容指定在外部服务器的URL,如果你希望将文件在一个内容分布式网络(CDN)上主办,但你需要确保,宿主服务器已经启用 跨域资源共享(Cross Origin Resource Sharing, CORS)。查看 WebGL networking 页面的指南来获取更多关于CORS的信息。
增量工程
你的项目通过IL2CPP生成的C++代码时增量编译的;即,在最新工程中改变的C++代码会被再次编译。没有改变的源代码复用为之前工程生成的相同目标文件。用于增量C++工程的对象文件存储在你的Unity项目 Library/il2cpp_cache目录中。
为了得到一个干净的,从零开始都没有使用增量编译所生成C++代码的工程,删除 你Unity项目目录中 Library/il2cpp_cache目录。注意,如果Unity编辑器版本不同于用于之前WebGL工程的编辑器,Unity会自动生成一个干净的,从零开始的工程。