分析并优化 Unity Web 构建
本文提供了有关如何优化 Unity Web 项目的提示。
Unity Web 平台(以前称为“WebGL”)支持包括多项关键进步,可减少更多设备的摩擦,并利用最新的图形 API 来确保即使是最雄心勃勃的网络游戏也能实现流畅的帧速率和卓越的性能。
这包括对 WebGL 的支持,WebGL 是一种可以高速向浏览器呈现 2D 和 3D 图形的 JavaScript API。Google Chrome、Mozilla Firefox、Safari 和 Microsoft Edge 均支持 WebGL 2 内容。WebGL 2 基于 OpenGL ES 3.0
无论您的图形 API 如何,您都应该致力于使 Unity Web 游戏体积小巧,以便高效地分发和嵌入到网站和社交媒体中。您还可以使用 Web 构建进行原型设计和游戏开发,其中轻松分发是关键,以及进行测试,即使您针对的是另一个平台。
网络游戏无法访问本地文件或硬件,并且性能通常比本地编译的游戏略低。
注意:Unity 6 测试版(2023.3.0b1 测试版)现已提供新 API WebGPU 的早期访问版本。WebGPU 仍处于开发阶段,不建议用于生产用例。
WebGPU 的设计目标是利用和向网络展示现代 GPU 功能。这个新的 Web API 提供了一个现代图形加速接口,该接口通过本机 GPU API(例如 DirectX12、Vulkan 和 Metal)在内部实现。具体的本机实现将取决于浏览器的平台和可用的图形驱动程序。有关如何开始以及其他 WebGPU 演示的详细信息,可以在 图形论坛中找到。
要在 Unity Web 平台上部署,首先需要将 Web 模块添加到 Unity Editor 以创建 Web 构建。在 Unity Hub 中找到安装,单击设置图标,然后选择 添加模块。
在新对话框中,向下滚动找到 Web Build Support,选择它,然后单击 Done。
重新打开您的项目,并在 File > Build Settings下切换目标平台。在开发游戏时使用开发构建选项。它提供额外的调试信息,如堆栈跟踪、详细的错误消息和日志信息,可以帮助您排除故障并对游戏进行更改。您可以对游戏代码、资产或设置进行小幅更改,然后在浏览器中快速重建和测试这些更改,而无需完整的构建过程。
只需确保取消选中“构建设置”中“开发构建”选项即可。
选择 “构建并运行” 来创建在浏览器中运行的游戏版本以进行游戏测试。Google Chrome 是进行游戏测试的理想选择,因为它提供了许多开发工具。
系统将提示您选择构建的位置。构建中的文件包括一个 index.html 文件,该文件将 HTML5 Canvas 元素添加到文档对象模型 (DOM),该模型是构成 Web 上文档结构和内容的对象的数据表示。游戏被渲染到该画布上。构建文件还包括一个 TemplateData 文件夹和一个 Build 文件夹。TemplateData 文件夹包含页面上使用的 HTML 资产,例如浏览器地址栏中使用的网站图标和页面 HTML 标记中使用的图像。
您还可以设置自动构建,其中 Unity Build Automation 就是其中一种选项。
您可以将内置渲染管线或通用渲染管线 (URP) 用于 Web 游戏。但是,我们推荐 URP,因为它可以提供高效的内容定制以及针对多种硬件设备的扩展。
通过电子书《 面向高级 Unity 创作者的通用渲染管线简介》获得有关将项目从内置渲染管线迁移到 URP 的深入指导。
当以控制台为目标时,您会对内存、CPU 和 GPU 使用情况有精确的规格。网络是一个完全不同的野兽。为了让您的游戏能够被最广泛的受众所接受,您需要确保它能够在内存受限的环境中正常运行。
以下是一些关于如何让你的游戏在低端硬件上流畅运行的技巧,摘自电子书 《优化你的手机游戏性能》。
1.优化您的游戏资产
优化网络的纹理和模型等资产,例如,使用压缩纹理并在适用的情况下减少模型中的多边形数量。虽然没有一成不变的规则,但您的团队需要就一些一般准则达成一致,以确保绩效的一致性。
2.使用对象池
对象池 是一种可以通过重用对象而不是创建和销毁新对象来帮助您提高性能的技术。这对于有大量生成和消失的游戏中很有用。飞轮等其他编程设计模式也可能有帮助。请参阅电子书《 通过游戏编程模式提升你的代码》,了解有关如何在 Unity 项目中实现设计模式的高级技巧。
3.使用通用渲染管线和 SRP Batcher
使用 Unity 的 SRP Batcher 批处理系统提高性能,该系统可根据场景加快 CPU 渲染速度。它的工作原理是根据共享的材质属性(例如着色器和纹理)将绘制调用分组在一起,从而减少渲染期间所需的状态改变的次数。
4.使用遮挡剔除
Unity 中的 遮挡剔除 系统可以通过仅渲染玩家可见的对象来帮助提高性能。遮挡剔除最适用于小型、界限分明的区域被实体游戏对象 (如由走廊连接的房间) 彼此分隔的场景。
5.使用内置 LOD(细节级别)系统
Unity 的内置 LOD 系统 通过降低距离玩家较远的物体的复杂性来提高性能。随着摄像机和物体之间的距离增加,LOD 系统会自动将物体的高细节版本与低细节版本交换,从而减少渲染工作量,同时保持一致的外观。
6.尽可能烘焙灯光
通过使用 光照贴图 和 光照探针预先计算场景的照明信息来提高性能。
7.减少不必要的字符串创建或操作
在 C# 中,字符串是引用类型,而不是值类型。避免解析基于字符串的数据文件(例如 JSON 和 XML);而是将数据存储在 ScriptableObjects 或 MessagePack 或 Protobuf 等格式中。您还可以考虑使用二进制格式来保存持久游戏数据(保存游戏)。如果您需要在运行时构建字符串,请使用 StringBuilder 类。
8.尝试可寻址资源系统
可寻址资产系统 通过“地址”或别名加载 AssetBundles,提供了一种管理内容的简化方法。该统一系统从本地路径或远程内容分发网络(CDN)异步加载。
9.限制后期处理效果
全屏后期处理效果可能会降低性能,因此在游戏中请谨慎使用它们。
当您创建 Unity Web 构建时,Unity 会使用 模板 生成网页来显示您的游戏。
默认模板为:
- 0(默认值)灰色画布上带有加载栏的白色页面
- 最小:运行游戏所需的最小样板
- 渐进式 Web 应用程序 (PWA):这包括一个 Web 清单文件和服务工作者。在合适的桌面浏览器中,这将在地址栏中显示一个安装按钮,用于将游戏添加到玩家的可启动应用程序中。
创建自定义 HTML 页面最简单的方法是从以下三个模板之一开始,您可以通过以下方式找到这些模板 <UnityInstallation>/PlaybackEngines/WebGLSupport/BuildTools/WebGLTemplates/。 在 Mac 上,您可以在应用程序文件夹中找到 Unity 安装文件夹。
复制一个模板,将其放在您自己的 Project/Assets/WebGLTemplates 文件夹中,然后重命名,以便您以后识别它。您现在可以对其进行自定义以适合游戏内容、部署站点和目标平台。
项目的 WebGLTemplates 文件夹中的模板出现在 编辑 > 项目设置... > 播放器 > 分辨率和演示 面板中。模板的名称与其文件夹相同。为了给此选项提供缩略图以便于参考,请将 128 x 128 像素的图像添加到模板文件夹并将其命名为 thumbnail.png。
在构建过程中,Unity 会预处理模板文件并评估这些文件中包含的所有宏和条件指令。它查找并用编辑器提供的值替换所有宏声明,并自动预处理模板文件夹中的所有 .html、.php、.css、.js 和 .json 文件。
例如,看一下这行代码:
<canvas id="unity-canvas" width={{{ WIDTH }}} height={{{ HEIGHT }}} tabindex="-1"></canvas>
如果在“分辨率和演示”面板中将 “默认画布宽度”设置为 960,将 “默认画布高度” 设置为 600,则预处理后的代码将如下所示:
<canvas id="unity-canvas" width="960" height="600" tabindex="-1"></canvas>.
三重花括号指示编译器查找所指示变量的值。
您还将在默认模板中找到使用 #if、 #else 和 #endif的条件指令的示例:
#if 表达式
//如果 EXPRESSION 计算结果为真值
#else
//如果 EXPRESSION 的计算结果不是真值
#endif
如果您想使用自定义模板,Unity Asset Store 提供了多种选项。
您经常希望您的游戏调整浏览器窗口的大小以适应响应式设计,这需要您调整加载代码。您可以使用 JavaScript 中的“Promise”来实现这一点,它表示尚未完成但预计在将来完成的操作。
在每个模板的 index.html 页面中(参见下面的代码示例),找到 script.onload。script.onload 是当 Unity 引擎脚本完成加载时触发的事件。在此之前,您有两个全局变量:myGameInstance,它保存对 Unity 实例的引用,以及 myGameLoaded,它指示游戏是否已完成加载,默认为 false。它们被声明为 var,因此它们具有全局范围并可以在脚本中的任何位置访问。
调用createUnityInstance()函数来创建Unity游戏的新实例。此函数返回一个 Promise,当游戏完全加载并准备好渲染时(createUnityInstance Promise 的 then 块)该 Promise 就会被解析。
在 then() 内部,myGameInstance 被分配了 Unity 实例,并且 myGameLoaded 被设置为 true,表示游戏现已准备就绪。然后调用 resizePage() 函数来初始设置游戏的大小,并向窗口的调整大小事件添加一个事件监听器,以便在调整窗口大小时可以更新游戏的大小。请参阅下面的代码片段。
然后,我们在脚本的底部有 resizePage 函数,如下面的代码片段所示,该函数用于调整游戏大小以匹配窗口的大小。如果游戏已加载,它会设置显示游戏的画布的样式值以匹配窗口大小,使其填满窗口:
函数调整页面大小(){
如果(myGameInstance!==未定义&&myGameLoaded===真)
{
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
}
}
许多针对浏览器的游戏都需要与 JavaScript 代码交互,以允许您调用 Web 服务来支持用户登录、高分表等,或与浏览器 DOM 交互。您直接添加的任何 JavaScript(因此可以从 C# 脚本调用)都需要具有 .jslib 扩展名并放置在 Assets/Plugins 文件夹中。它应该被包装在mergeInto方法中。这需要两个参数:LibraryManager.library 然后是包含一个或多个函数的 JavaScript 对象。这些函数是标准 JavaScript。GetExchangeRates 展示了如何使用下面简单的 JSON 传送 Web 服务。
当你创建构建时,这些函数将被添加到 Build/<你的游戏名称>.framework.js 文件中。您可以通过将函数声明为 DllImport 从 C# 脚本调用这些函数,如以下代码示例所示:
公共类SphereController:MonoBehaviour
{
[DllImport("__Internal")]
private static extern void GetExchangeRates();
私有无效开始()
{
GetExchangeRates();
}
}
更多信息
除了 C# 调用 JavaScript 函数之外,JavaScript 还可以调用 C# 方法。所涉及的机制使用消息传递协议:
myGameInstance.SendMessage('MyGameObject','MyFunction')
myGameInstance.SendMessage(‘MyGameObject’, ‘MyFunction’, 5)
myGameInstance.SendMessage('MyGameObject', 'MyFunction', '字符串')
要使用 SendMessage,您需要引用范围内的游戏实例。通常的技术是通过添加全局变量并在 script.onload Promise 的 then 块中分配它来编辑 index.html,如前所述。这个简单的函数被添加为 MonoBehaviour 组件的一部分,该组件附加到名为 Sphere的游戏对象上。
public void SetHeight(浮动高度)
{
Vector3 pos = 变换.位置;
pos.y = height;
transform.position = pos;
}
您可以使用 F12 打开 Chrome 的控制台并直接输入:
myGameInstance.SendMessage('Sphere', 'SetHeight', 3)
按 Enter 键调用函数 移动球体。仅当您设置了 “在后台运行” 或将 Application.runInBackground 设置为 true 时,移动才会反映在渲染中。这是因为默认情况下仅当画布窗口具有焦点时才会发生渲染。
在针对浏览器平台进行调试时使用 Debug.Log。任何消息都会发送到浏览器控制台。对于 Chrome,您可以通过按 F12 并切换到控制台选项卡来找到它。但 Debug 类提供了更多选项。使用 Debug.LogError,控制台将提供有用的堆栈跟踪。
更多信息
我们建议您在开发期间使用开发构建选项,但在将游戏部署到实时站点时取消选中此选项。对于发布版本,您可以选择压缩。使用压缩时,您可能需要调整服务器上的设置;有关如何执行此操作的提示,请参阅 手册 。
在整个开发周期中对您的项目进行分析非常重要,这样您才能及时发现性能问题。Unity Profiler 是识别和修复游戏中性能瓶颈的良好工具。它跟踪 CPU 和内存的使用情况,帮助您识别游戏中需要优化的区域。您还可以同时使用 配置文件分析器、 内存分析器和 Web 诊断覆盖 。
下载电子书《Unity 游戏分析终极指南》, 深入了解 Unity 中的分析。
让我们了解一些开始分析 Unity Web 构建的技巧。
启用 Unity 的分析器
在编辑器中转到 文件 > 构建设置 ,然后选择 开发构建 和 自动连接分析器 以将分析器与 Web 构建一起使用。
选择 CPU 使用率模块
使用 此模块 分析代码的性能并找出导致性能问题的区域。分析函数调用、脚本执行和垃圾收集等元素。
选择内存分析器模块
与其他平台相比,Unity Web 构建的内存资源有限。使用 此模块 分析应用程序的内存使用情况并确定需要优化的领域。
使用 Chrome DevTools 性能面板
Chrome DevTools 包含一个 性能 面板,可帮助您深入了解游戏中的瓶颈。除其他功能外,它还提供了用于在 JavaScript 文件中添加断点的 “源” 面板和用于查看调试消息和输入 JavaScript 代码的 “控制台” 面板。
测量不同设备上的性能
这将帮助您识别特定于特定设备或浏览器的性能问题,并帮助您相应地优化游戏。
减少绘制调用次数
绘制调用是 Unity Web 构建的主要性能瓶颈之一。使用 Unity Profiler 识别绘制调用次数较多的区域并 尝试减少它们。
分析低端设备的性能
在低端设备上进行测试以确保您的应用程序针对各种硬件进行了优化。
在分析期间启用“在后台运行”
如果在 WebGL 播放器设置中启用了 “在后台运行” 或启用了 Application.runInBackground,则当画布或浏览器窗口失去焦点时,您的内容将继续运行,这在分析时非常有用。
Unity Web 构建是向广大受众分发游戏的绝佳方式。在开发过程中,您应该努力将几何图形和纹理保持在适当的大小,减少绘制调用,并在各种设备上进行分析和测试。最后,使用 URP 确保在最广泛的硬件上实现稳定的性能。
更多信息
提前体验 Unity 2023.3 中的全新 WebGPU 后端
在 Unity 最佳实践中心查找 Unity 的所有高级电子书和文章。