WEBGL技术专题
# Unity WebGL 开发
WebGL 允许您将实时交互式 3D 图形发布到浏览器中。Unity 编辑器中的 WebGL 选项允许您将内容发布为 JavaScript 程序,这些程序使用 HTML5/JavaScript、WebAssembly、WebGL 渲染 API 和其他 Web 标准在 Web 浏览器中运行 Unity 内容。
# Emscripten工具链
Unity 使用 IL2CPP 将 C# 脚本中的 .NET 游戏代码转换为 Wasm。IL2CPP 获取 .NET 字节码并将其转换为相应的 C++ 源文件,然后使用 Emscripten 进行编译以将脚本转换为 Wasm。
Emscripten简介
- 诞生背景
Web 技术突飞猛进,但是有一个领域一直无法突破:游戏。
游戏的性能要求非常高,一些大型游戏连 PC 跑起来都很吃力,更不要提在浏览器的沙盒模型里跑了!但是,尽管很困难,许多开发者始终没放弃,希望让浏览器运行 3D 游戏。
2012年,Mozilla 的工程师 Alon Zakai 在研究 LLVM 编译器时突发奇想:许多 3D 游戏都是用 C / C++ 语言写的,如果能将 C / C++ 语言编译成 JavaScript 代码,它们不就能在浏览器里运行了吗?众所周知,JavaScript 的基本语法与 C 语言高度相似。
于是,他开始研究怎么才能实现这个目标,为此专门做了一个编译器项目 Emscripten。这个编译器可以将 C / C++ 代码编译成 JS 代码,但不是普通的 JS,而是一种叫做 asm.js 的 JavaScript 变体。
- 什么是Emscripten
Emscripten 是一个工具链,作用是通过 LLVM 来编译生成 asm.js、WebAssembly 字节码,目的是让你能够在网页中接近最快的速度运行 C 和 C++,并且不需要任何插件。
Emscripten 是一种基于 LLVM 的编译器,理论上能够将任何能够生成 LLVM 位码的代码编译成 javascript 的严格子集 asm.js,实际上主要用于将 C/C++ 代码编译成 asm.js。
# 浏览器兼容性
- Unity WebGL 对桌面浏览器的支持因浏览器而异。
操作系统和浏览器需要满足的条件如下
- 浏览器支持 WebGL 2.0。
- 符合 HTML 5 标准。
- 是 64 位并支持 WebAssembly。
- 桌面系统支持的有 Windows、MacOS、Linux。
- 桌面浏览器支持的有谷歌浏览器、火狐浏览器、苹果浏览器、微软边缘浏览器。
- 桌面和移动设备支持不同的纹理压缩格式。
不同平台支持的纹理压缩格式如下
- 桌面浏览器纹理压缩格式:DXT。
- 移动浏览器纹理压缩格式:ASTC 、ETC2。
查看按平台支持的纹理压缩格式请点击链接:
https://docs.unity.cn/cn/2022.3/Manual/class-TextureImporterOverride.html
- Unity WebGL 不支持移动设备。它可能适用于高端设备,但当前设备通常功能不强大,并且没有足够的内存来支持 Unity WebGL 内容。
注意事项
- Unity WebGL 还支持最新版本的基于 Chromium 的 Edge 浏览器。
- Apple Safari 在 Safari 15 之前的版本中不支持 WebGL 2。
- Apple Safari 不支持在 iFrame 中运行内容的 IndexedDB。
- 在 Linux 上,您可能必须通过包管理器(例如 GStreamer 包)安装高级音频编码 (AAC) 编解码器支持。
# 图形渲染
WebGL 是一种用于在 Web 浏览器中渲染图形的 API,基于 OpenGL ES 图形库的功能。
WebGL 1.0 大致与 OpenGL ES 2.0 功能相匹配。
WebGL 2.0 大致与 OpenGL ES 3.0 功能相匹配。
- 帧缓存:默认情况下,Unity WebGL 在每帧后清除绘图缓冲区,这意味着无论 Camera.clearFlags 设置如何,帧缓冲区的内容都会被清除。
- 反射探针:Unity WebGL 支持所有反射探针。WebGL 1.0 不支持平滑实时反射探针。
- 全局光照:Unity WebGL 仅支持烘焙 GI,仅支持非定向光照贴图,目前不支持实时全局照明。
- 抗锯齿:Unity WebGL 对于大多数(但不是全部)浏览器和 GPU 组合均支持抗锯齿功能。
- 视频渲染:请使用 VideoPlayer 组件中的 URL 选项,并将资源放置在 StreamingAssets/ 目录中,以使用浏览器的内置网络流。
- 渲染路径:WebGL 1.0 Unity WebGL 支持前向渲染。WebGL 2.0 Unity WebGL 仅支持延迟渲染。
- 色彩空间:WebGL 2.0 Unity WebGL 仅支持线性颜色空间渲染。
- 字体渲染:由于它无法访问用户计算机上安装的字体,请确保将它们包含在项目文件夹中(包括国际字符的任何后备字体,或粗体/斜体版本字体),并设置为后备字体名称。
- 着色器:WebGL 1.0 规范对 GLSL 着色器代码施加了一些限制,这些限制比大多数 OpenGL ES 2.0 实现更具限制性。WebGL 对于使用哪些值来索引数组或矩阵有特定的限制。由于 WebGL 中的可用内存有限,您应该避免包含不需要的着色器变体,这可能会导致不必要的内存使用。
采用下面的代码可以防止图形被清除:
script.onload = () => {
// 在 WebGL 模板中将此文件添加到 index.html 文件中
config['webglContextAttributes'] = {"preserveDrawingBuffer": true};
createUnityInstance(canvas, config, (progress) => }
2
3
4
5
WebGL 2.0 优点
- 更好的性能。
- 支持 GPU 实例化和定向光照贴图。
- 标准着色器中的内容质量很高,着色器代码中的索引和循环没有限制。
- 可以在运行时使用 SystemInfo.graphicsDeviceType 来确定 Unity 实例是使用 OpenGL ES3 (WebGL2.0) 还是 OpenGL ES2 (WebGL1.0) 进行渲染。
# 音频
- 由于 Unity 使用 FMOD 来管理平台的音频,因此 Unity WebGL 仅包括有限的基本音频功能。
特别说明
FMOD 依赖于线程,而 WebGL 不支持线程。因此,Unity 使用基于内部 Web Audio API 的实现,使浏览器能够处理音频播放和混合。
- Unity WebGL 可以导入 AAC 格式的 AudioClip 文件,大多数浏览器都支持该格式。
- 要获得 Linux 上的音频剪辑支持,请确保您已安装 ffmpeg 软件包。
- 要在 Unity 中通过 WebGL 使用压缩音频,请将 AudioClip loadType 设置为以下选项之一:CompressedInMemory、DecompressOnLoad。
CompressedInMemory:使用它来压缩磁盘上的音频,并在加载到应用程序内存后保持压缩状态。
DecompressOnLoad:使用它来压缩磁盘上的音频,类似于 CompressedInMemory,并在加载到应用程序内存时解压缩。
# 平台支持
- 由于浏览器对文件系统的访问受到限制,WebGL 版本不支持 Unity 缓存和缓存脚本 API。对资产数据和 AssetBundle 的网络请求会缓存在浏览器缓存中。
- 由于 JavaScript 中缺乏线程支持,因此不支持线程。这既适用于 Unity 内部使用线程来加速性能,也适用于在脚本代码和托管 dll 中使用线程。本质上,System.Threading 命名空间中的任何内容都不受支持。您无法在脚本中编写 WebGL 中的线程或 SIMD 代码,但由于某些引擎部件是多线程或 SIMD 优化的,因此它们在 WebGL 上的性能较低。例如,WebGL Skinning 是多线程且经过 SIMD 优化的。
- 出于安全考虑,浏览器不允许直接访问 IP 套接字进行网络连接。
- WebGL 是一个 AOT 平台,因此它不允许使用 System.Reflection.Emit。 这在所有其他 IL2CPP 平台、iOS 和大多数控制台上都是相同的。
- WebGL 支持 Unity 分析器 Profiler。
# 内存
- Unity WebGL 可用内存量因以下因素而异:您使用的设备、操作系统、浏览器以及它是在 32 位处理器还是 64 位处理器上运行、浏览器的 JavaScript 引擎解析代码所需的内存量、浏览器为每个选项卡使用单独进程,还是内容需要与所有其他打开的选项卡共享内存空间。
- Unity 堆:Unity 使用内存堆来存储所有 Unity 引擎运行时对象,其中包括托管和本机对象、加载的资源、场景和着色器。Unity 堆是分配的内存的连续块,堆大小随着应用程序的运行而扩展,最多可达 2GB。如果浏览器无法在地址空间中分配连续的内存块,自动调整堆大小可能会导致应用程序崩溃。因此,保持 Unity 堆大小尽可能小非常重要。
- 资产数据:当您创建 Unity WebGL 构建时,Unity 会生成一个 .data 文件,这是一个虚拟内存文件系统,它包含应用程序启动所需的所有场景和资产。为了减少内存使用,您可以将资产数据打包到 AssetBundles 中。AssetBundles 提供对资源下载的完全控制,您可以控制应用程序何时下载资产以及运行时何时卸载它。您可以卸载未使用的资源以释放内存。AssetBundles 直接下载到 Unity 堆中,因此不会导致浏览器进行额外分配。启用数据缓存可自动将内容中的资产数据缓存在用户计算机上。这意味着您无需在以后的运行期间重新下载该数据。
- 垃圾收集:垃圾收集是定位和释放未使用内存的过程,垃圾收集器收集未使用的内存后,会在 Unity 堆内重新分配它。然后,垃圾收集器将检查堆栈并注册已加载的对象引用。如果垃圾收集器发现不再引用的对象,它将释放该对象使用的内存。WebGL 垃圾收集在堆栈为空时运行。堆栈是 Unity 堆的一部分,但不是堆本身。
- 缓存行为:在 Unity WebGL 中,缓存 API 允许您将缓存在 .data 文件和 AssetBundles 中的资源数据存储在浏览器缓存中。Unity WebGL 加载器使用 IndexedDB API 实现数据缓存。此选项允许您缓存太大而浏览器无法本地缓存的文件。而浏览器通常会限制您可以在其缓存中存储的数量以及可以缓存的最大文件大小。这通常不足以让应用程序顺利运行。(要点:缓存在 IndexedDB 上,不是浏览器上)浏览器会自动存储(缓存)某些文件类型,例如 .html、.js、.css、.json、.jpg、.png,因此它们不需要显式存储在 WebGL 缓存中。WebGL 缓存的典型候选者包括大型文件和使用自定义文件格式的文件。
# 网络
- UnityWebRequest 类。Unity 支持 WebGL 中的 UnityWebRequest 类。为了实现 UnityWebRequest 类,Unity 使用 JavaScript Fetch API,该 API 使用浏览器来处理 Web 请求。这对跨域资源的访问施加了安全限制。如果您向非 Unity 内容托管服务器发送 Web 请求,则发送请求的服务器必须授权 Unity 内容。
以下示例演示了如何添加 Access-Control 标头,以允许 Unity WebGL 从任何源点访问 Web 服务器上的资源:
该示例包括常见的请求标头,并允许 GET、POST 或 OPTIONS 方法:
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Origin": "*",
2
3
4
5
6
7
- Unity 多人游戏(以前称为 UNet)。
- 您可以使用 JavaScript 中的 WebSockets 或 WebRTC 来实现您自己的网络。(借助资源店里的第三方插件来实现)
- 您不能使用 .NET 网络类,因为 JavaScript 代码无法直接访问 IP 套接字来实现网络连接。
注意
请注意,千万不能使用 .NET 网络类,因为 JavaScript 代码无法直接访问 IP 套接字来实现网络连接。
# 调试
- 使用浏览器控制台查看信息:Unity WebGL 无法访问您的文件系统,因此它不会像其他平台那样写入日志文件。但是,它确实会将所有日志记录信息(例如Debug.Log,Console.WriteLine或 Unity 的内部日志记录)写入浏览器的 JavaScript 控制台。
- 开发版支持:出于调试目的,您可能希望在 Unity 中进行开发构建(打开"构建设置"窗口并启用"开发构建"复选框)。开发版本允许您连接探查器,并且 Unity 不会缩小它们,因此发出的 JavaScript 代码仍然包含人类可读的(尽管是C++-mangled)函数名称。如果您在使用 Debug.LogError, or when an exception occurs and exception support is disabled。与拥有完整异常支持时可能出现的托管堆栈跟踪不同,这些堆栈跟踪具有损坏的名称,并且不仅包含托管代码,还包含内部 UnityEngine 代码。
提示
启用此设置以在构建中包含脚本调试符号和探查器。当您启用此功能时,Unity 会设置 DEVELOPMENT_BUILD 脚本定义。仅当您想要测试应用程序时才使用此设置,因为开发版本不会缩小内容,它们的分发量很大。
- 异常支持:WebGL 具有不同级别的异常支持,但默认情况下,Unity WebGL 仅支持显式抛出的异常。您可以启用完整异常支持,这会在 IL2CPP 生成的代码中发出额外的检查,以捕获对托管代码中的空引用和越界数组元素的访问。这些额外的检查会明显影响性能并增加代码大小以及加载时间,因此您应该仅将其用于调试。完全的异常支持还会发出函数名称,以便为托管代码生成堆栈跟踪。出于这一原因,对于未捕获的异常和 Debug.Log 语句,堆栈跟踪将出现在控制台中。使用 System.Environment.Stacktrace 可获取堆栈跟踪字符串。
# 构建
- [ExampleBuild].loader.js :网页加载 Unity 内容所需的 JavaScript 代码。
- [ExampleBuild].framework.js :JavaScript 运行时和插件。
- [ExampleBuild].wasm :WebAssembly 二进制文件。
- [ExampleBuild].mem :用于初始化播放器堆内存的二进制图像。Unity 仅为多线程 WebAssembly 构建生成此文件。
- [ExampleBuild].data :资源数据和场景。
- [ExampleBuild].symbols.json :调试错误堆栈跟踪所需的调试符号名称。仅当启用 Debug Symbols 选项时 (File > Build Settings > Player Settings),才会为 Release 构建生成此文件。
- [ExampleBuild].jpg :背景图像,在构建加载时显示。仅当播放器设置(文件>构建设置>播放器设置>启动图像)中的背景图像可用时才会生成此文件。
# 浏览器访问设备功能
- Unity WebGL支持 WebCam 访问。目前,Unity WebGL 仅支持网络摄像头设备。
# WebGL性能相关总结
提示
一般来说,WebGL 性能接近 GPU 上的本机应用程序,因为 WebGL 图形 API 使用 GPU 进行硬件加速渲染。唯一的例外是将 WebGL API 调用和着色器转换为操作系统图形 API(通常是 Windows 上的 DirectX、Mac 和 Linux 上的 OpenGL)的少量开销。在 CPU 上,Emscripten 将您的代码转换为 WebAssembly,其性能取决于您使用的 Web 浏览器。
- 选择 WebGL2.0 可以提高性能。
- 通过展开 "其他设置">"堆栈跟踪",在 WebGL 的播放器设置中将 "异常支持" 设置为 "无",这样可以提高性能。
提示
- None:如果您不需要任何异常支持,请选择此项。这提供了最佳的性能和最小的构建。使用此选项,抛出的任何异常都会导致您的内容因该设置中的错误而停止。
- 仅显式抛出异常(默认):选择此选项可捕获从脚本中的语句显式指定的异常 throw,并确保 finally 调用块。请注意,选择此选项会使脚本生成的 JavaScript 代码更长且更慢;仅当脚本是项目中的主要瓶颈时,这才可能成为问题。
- Full Without Stacktrace:选择此选项可捕获从脚本中的语句中显式指定的异常(与"仅显式抛出异常" throw 选项中的相同),还有 Null 引用 和 越界数组访问。
- Full With Stacktrace:此选项与上面的选项类似,但它也捕获堆栈跟踪。Unity 通过在代码中嵌入检查来生成这些异常,因此此选项会降低性能并增加浏览器内存使用量。仅将其用于调试,并始终在 64 位浏览器中进行测试。
- 在某些情况下,您可能希望以较低的帧速率运行 WebGL 内容,以减少 CPU 使用率。例如,在其他平台上,您可以使用 Application.targetFrameRate API 来执行此操作。如果您不想限制性能,请将此 API 设置为默认值 –1,而不是较高的值。这允许浏览器调整帧速率,以在浏览器的渲染循环中实现最平滑的动画,并且可能会产生比 Unity 尝试执行自己的主循环计时来匹配目标帧速率更好的结果。
- 某些 Web 浏览器不支持 sRGB DXT 纹理压缩。因此在使用线性渲染时会降低渲染性能的质量,原因是所有 DXT 纹理都要在运行时解压缩。
# WebGL构建
# 使用 AssetBundles 减少加载时间
由于您必须在 Unity 显示内容开始之前下载所有资产数据,因此请考虑将资产从主数据文件移出并移至 AssetBundles。通过将资产移动到 AssetBundles 您可以为内容创建一个小型加载器场景,该场景会在用户继续浏览您的内容时动态按需加载资产。AssetBundles 还有助于资产数据内存管理。您可以通过调用 AssetBundle.Unload 从内存中卸载不再需要的资产数据。
注意事项
- 当您在 AssetBundle 中使用主构建中未使用的类类型时,Unity 可能会从构建中删除这些类的代码。当尝试从 AssetBundle 加载资源时,这可能会导致失败。使用 BuildPlayerOptions.assetBundleManifestPath 来修复该问题。
- WebGL 不支持线程。由于 HTTP 下载只有在下载后才可用,因此 Unity WebGL 构建需要在下载完成后在主线程上解压缩 AssetBundle 数据,从而阻塞主线程。为了避免这种中断,LZMA AssetBundle 压缩不适用于 WebGL 上的 AssetBundle,而是使用 LZ4 进行压缩,LZ4 可以按需高效解压缩。如果您需要比 LZ4 提供更小的压缩,您可以将 Web 服务器配置为在 AssetBundles 上使用 gzip 或 Brotli 压缩(在 LZ4 压缩之上)。
- WebGL 支持 AssetBundle 使用 UnityWebRequestAssetBundle.GetAssetBundle 进行缓存。此方法使用 IndexedDB 浏览器中的 API 在用户设备上存储缓存。某些浏览器可能具有有限的支持 IndexedDB,并且任何浏览器都可能请求用户授权才能在磁盘上存储数据。
# 减小构建文件大小
以 WebGL 为目标进行发布时,必须保持较低的构建大小,让用户在内容启动之前等待合理的下载时间,这一点很重要。
- WebGL 构建注意事项
在纹理导入器 Texture Importer 中为所有压缩纹理指定 Crunch 纹理压缩格式。
不要部署开发版本,它们没有被压缩或缩小,因此文件大小要大得多。
在 Player 设置窗口中,(单击Edit > Project Settings > WebGL)展开 Publishing Settings,然后将 Enable Exceptions 设置为 None(如果您的构建中不需要异常)。
在播放器设置 > 其他设置面板中启用 Strip Engine Code,以确保高效构建。
使用第三方托管 dll 时,请注意它可能带有会增加生成代码大小的依赖项。
- 代码剥离
默认情况下,Unity 会从构建中删除所有未使用的代码。可通过 Player 设置(菜单:Edit > Project Settings,然后选择 Player 类别)来更改此设置:选择 Other Settings 面板访问 Strip Engine Code 选项。最好在启用剥离的情况下进行构建。
启用代码剥离后,Unity 扫描会项目以查找是否使用了 UnityObject 派生的任何类(通过在脚本代码中或在场景中的序列化数据中引用)。然后从构建中删除所有未使用这些类的 Unity 子系统。这样可减少构建代码,从而减小下载和要解析的代码(因此代码运行速度更快,且占用的内存更少)。
代码剥离产生的问题
如果代码剥离时剥离了实际需要的代码,可能会导致项目出现问题。
例如,如果在运行时加载的 AssetBundle 所包含的类未包括在主构建中,因此从项目中删除了这些 AssetBundle,这种情况下就可能出问题。
发生这种情况时,浏览器的 JavaScript 控制台中会显示错误消息(随后可能会显示更多错误)。
例如:Could not produce class with ID XXX。要解决这些错误,请在类 ID 参考中查找该 ID(如上例中的 XXX),看哪个类在尝试创建实例。
在这种情况下,可强制 Unity 在构建中包含该类的代码,方法是向脚本或向场景添加对该类的引用,或者在项目中添加 link.xml 文件。
下面是一个确保 Collider 类和物理模块保留在项目中的示例。
将此 XML 代码添加到名为 link.xml 的文件中 ,然后将该文件放入您的 Assets 文件夹中。
<linker>
<assembly fullname="UnityEngine">
<type fullname="UnityEngine.Collider" preserve="all"/>
</assembly>
</linker>
2
3
4
5
如果怀疑剥离导致构建出现问题,还可尝试在测试期间禁用 Strip Engine Code 选项。
通过查看构建中包含哪些模块和类可以优化项目的剥离功能,但 Unity 未提供方便的方法来进行此操作。不过,若要了解包含的类和模块的概况,可在进行构建之后查看生成的文件 Temp/StagingArea/Data/il2cppOutput/UnityClassRegistration.cpp。
请注意,Strip Engine Code 选项仅影响 Unity 引擎代码。IL2CPP 始终会从托管的 dll 和脚本中剥离字节代码。需要通过反射(而不是通过代码中的静态引用)来动态引用托管的类型时,这可能会导致问题。如果需要通过反射来访问类型,可能还需要设置 link.xml 文件才能保留这些类型。
将构建的应用程序的文件大小保持在最低限度非常重要,尤其是对于移动设备或施加了大小限制的应用商店而言。减小大小的第一步是确定哪些资源对最终大小的影响最大,因为这些资源最有可能是需要优化的目标。执行构建后,可在 Editor 日志中找到此信息。选择 Console 窗口(菜单:Window > General > Console__),单击右上角的小下拉选单面板,然后选择 Open Editor Log__。
通常,纹理 (Textures)、声音 (Sounds) 和动画 (Animations) 等内容占用的空间最多,而脚本 (Scripts)、关卡 (Levels) 和着色器 (Shaders) 一般影响最小。
列表中显示的__文件标头 (File headers)__ 不是资源,实际上是添加到"原始"资源文件的额外数据,用于存储引用和设置。这些标头通常与资源大小差别很小,但如果在 Resources 文件夹中有许多大型资源,则该值可能会很大。
Editor 日志有助于识别可能要删除或优化的资源,但在开始之前应考虑以下事项:
- Unity 将导入的资源重新编码为其自己的内部格式,因此源资源类型的选择不是相关因素。例如,如果项目中有一个多层 Photoshop 纹理,在构建之前将其展平并压缩。将纹理导出为 .png 文件对构建大小没有任何影响,因此应该坚持使用在开发过程中最方便的格式。
- Unity 在构建期间会剥离大多数未使用的资源,因此无法通过从项目中手动删除资源来获得任何优化效果。唯一不会删除的资源是脚本(但无论如何,这些脚本通常都非常小)和 Resources 文件夹中的资源(因为 Unity 无法确定哪些是需要的,而哪些不是)。考虑到这一点,应确保 Resources 文件夹中的所有资源都是游戏所必需的资源。也许可以使用 AssetBundle 替换 Resources 文件夹中的资源;这样一来,Unity 就会动态加载资源,从而减小播放器大小。
关于减小构建大小的建议:
- 纹理:纹理通常在构建中占据最多空间,第一个解决方案是使用压缩的纹理格式。
- 网格和动画:可以压缩网格和导入的动画剪辑,使它们在游戏文件中占用较少的空间。要启用网格压缩,请选择网格,然后在 Inspector 窗口中将 Mesh Compression 设置为 Low、Medium 或 High。网格和动画压缩使用量化技术,这意味着占用更少的空间,但压缩可能会带来一定程度的不准确性。请针对具体模型尝试找到可接受的压缩程度。请注意,网格压缩只是生成较小的数据文件,在运行时不会减少使用的内存。减少动画关键帧会生成较小的数据文件,并会在运行时减少使用的内存;通常应始终启用该功能。
- 减小 .NET 库大小:Unity 支持两个 .NET API 兼容性级别:.NET 4.x 和 .NET Standard 2.0。.NET Standard 2.0 会将您限制在较小的 .NET API 子集中,这有助于减小大小。
# 纹理压缩
在 WebGL 中使用纹理压缩来创建基于目标平台支持的纹理压缩格式的构建。您在此处设置的纹理压缩格式值优先于播放器设置的纹理压缩格式值。要使用压缩纹理在桌面和移动浏览器上运行游戏,您可能需要创建两个构建目标:将 DXT 设置为桌面浏览器纹理压缩格式 和 将 ASTC 设置为移动浏览器纹理压缩格式。从脚本创建桌面和移动浏览器的构建,您可以使用脚本同时运行具有相应纹理压缩格式的桌面浏览器和移动浏览器的构建。例如:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Diagnostics;
using System.IO;
using UnityEditor.Build.Reporting;
public class comboBuild
{
//This creates a menu item to trigger the dual builds https://docs.unity.cn/ScriptReference/MenuItem.html
[MenuItem("Game Build Menu/Dual Build")]
public static void BuildGame()
{
//This builds the player twice: a build with desktop-specific texture settings (WebGL_Build) as well as mobile-specific texture settings (WebGL_Mobile), and combines the necessary files into one directory (WebGL_Build)
string dualBuildPath = "WebGLBuilds";
string desktopBuildName = "WebGL_Build";
string mobileBuildName = "WebGL_Mobile";
string desktopPath = Path.Combine(dualBuildPath, desktopBuildName);
string mobilePath = Path.Combine(dualBuildPath, mobileBuildName);
string[] scenes = new string[] {"Assets/scene.unity"};
EditorUserBuildSettings.webGLBuildSubtarget = WebGLTextureSubtarget.DXT;
BuildPipeline.BuildPlayer(scenes, desktopPath, BuildTarget.WebGL, BuildOptions.Development);
EditorUserBuildSettings.webGLBuildSubtarget = WebGLTextureSubtarget.ASTC;
BuildPipeline.BuildPlayer(scenes, mobilePath, BuildTarget.WebGL, BuildOptions.Development);
// Copy the mobile.data file to the desktop build directory to consolidate them both
FileUtil.CopyFileOrDirectory(Path.Combine(mobilePath, "Build", mobileBuildName + ".data"), Path.Combine(desktopPath, "Build", mobileBuildName + ".data"));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# WebGL部署
提示
要部署 WebGL 构建,您必须配置服务器并确保使用正确的响应标头,以便浏览器接收正确的响应并正确处理它。Unity 中有两个主要设置会影响服务器的设置方式:
- Compression Format:确定 Unity 在构建步骤中如何压缩文件。
- Decompression Fallback:确定当构建在浏览器中运行时 Unity 如何处理下载的文件。
# Compression Format
- gzip:这是默认选项。gzip 文件比 Brotli 文件更大,但构建速度更快,且所有浏览器都基于 HTTP 和 HTTPS 实现此格式的本机支持。
- Brotli:Brotli 压缩提供最佳压缩比。Brotli 压缩文件小于 gzip,但需要更长的压缩时间,因此会增加发布版本的迭代时间。Chrome 和 Firefox 仅原生支持基于 HTTPS 的 Brotli 压缩。
- Disabled:禁用压缩。如果要在后期处理脚本中实现您自己的压缩,请使用此选项。如果计划在托管服务器上使用静态压缩,也应该使用此选项。
# Web服务器配置
您可能需要调整服务器配置以匹配特定构建设置。具体而言,如果已使用其他服务器端配置来压缩托管的文件(这可能会干扰此设置),可能会出现问题。 为了使浏览器在下载应用程序期间以原生方式执行解压缩,需要在服务器响应中附加一个 Content-Encoding 标头。该标头必须与 Unity 在构建时使用的压缩类型相对应。