Version: 2021.2
构建和运行 WebGL 项目
WebGL:压缩构建和服务器配置

使用 WebGL 模板

本页面需要 JavaScript 概念和术语方面的预备知识。

构建 WebGL 项目时,Unity 会将播放器嵌入到 HTML 页面中,以便浏览器可以打开它。WebGL 模板是一种配置设置,使您可以控制此 HTML 页面的外观,以便您可以在 HTML 页面中测试、演示和预览 WebGL 应用程序。 要访问 WebGL 模板,请转到Player settings(菜单:Edit > Project Settings > Player),将特定于平台的设置设置为 WebGL,然后打开 Resolution and Presentation

播放器 Resolution and Presentation 窗口的图像。
播放器 Resolution and Presentation 窗口的图像。

默认情况下,WebGL 模板设置具有两个选项:

  • Default:一个白色页面,其中的灰色画布上有一个加载进度条。
  • Minimal:一个最小 WebGL 模板,只有运行 WebGL 内容所需的样板代码。

这些内置 HTML 页面对于测试和演示最小播放器非常有用。

还可以使用 JavaScript 构建和提供自己的 WebGL 模板以托管播放器。这对于生产用途非常有用,使您可以预览在最终部署的页面中托管的播放器。例如,如果 Unity 播放器内容通过外部调用接口与页面中的其他元素交互,则应使用包含这些交互元素的页面进行测试。

添加 WebGL 模板

要将自定义模板添加到项目,请导航到项目的 Assets 文件夹并创建一个名为 WebGLTemplates 的文件夹。每个模板都是 WebGLTemplates 文件夹中的子文件夹。每个模板子文件夹都包含一个 index.html 文件以及页面所需的任何其他资源,例如图像或样式表。

创建新的自定义 WebGL 模板的最简单方法是复制内置 Default 或 Minimal 模板。这些模板存储在 <Unity Installation>/PlaybackEngines/WebGLSupport/BuildTools/WebGLTemplates/ 下的相应子文件夹中。默认情况下,每个 Unity 项目都包含这些模板。复制一个模板并将它放在您自己的 Project/Assets/WebGLTemplates 文件夹中,并将它重命名为有意义的内容,以便您以后可以识别您的模板。

项目的 WebGLTemplates 文件夹中的模板会出现在 Unity Player Settings 的 WebGL Template 设置中。模板的名称与其文件夹相同。要为此选项提供缩略图以便于参考,请将 128x128 像素的图像添加到模板文件夹并将它命名为 thumbnail.png

模板变量、宏和条件指令

在构建过程中,Unity 会预处理模板文件并计算这些文件中包含的所有宏和条件指令。作为此过程的一部分,Unity 会查找所有宏声明并将其替换为编辑器提供的值。Unity 会自动预处理模板文件夹中的所有 .html、.php、.css、.js 和 .json 文件。

内部预处理器变量

以下内部预处理器变量引用项目中的数据,Unity 在构建时会根据编辑器提供的值向它们分配值。Javascript 宏和条件指令可以使用这些内部预处理器变量。

可变 类型 描述
COMPANY_NAME String 在 Player Settings 中定义的 Company Name。
PRODUCT_NAME String 在 Player Settings 中定义的 Product Name。
PRODUCT_VERSION String 在 Player Settings 中定义的 Version。
WIDTH Integer 在 Player Settings > Resolution and Presentation 中定义的 Default Canvas Width。
HEIGHT Integer Player Settings > Resolution and Presentation 中的 Default Canvas Height。
SPLASH_SCREEN_STYLE String 当 Splash Style Player Settings > Splash Image 设置为 Light on Dark 时,此变量设置为“Dark”值,否则设置为“Light”值。
BACKGROUND_COLOR String 表示以十六进制三元组形式定义的背景颜色。
UNITY_VERSION String Unity 版本。
DEVELOPMENT_PLAYER Boolean 如果启用了 Development Build 选项,则此变量设置为 true。
DECOMPRESSION_FALLBACK String 此变量设置为“Gzip”或“Brotli”,具体取决于使用的压缩方法以及构建中包含的解压缩程序。如果两者都不包含,则变量设置为空字符串。
TOTAL_MEMORY Integer 内存堆的初始大小(以字节为单位)。
USE_WASM Boolean 如果当前构建是 WebAssembly 构建,则此变量设置为 true。
USE_THREADS Boolean 如果当前构建使用线程,则此变量设置为 true。
USE_WEBGL_1_0 Boolean 如果当前构建支持 WebGL1.0 图形 API,则此变量设置为 true。
USE_WEBGL_2_0 Boolean 如果当前构建支持 WebGL2.0 图形 API,则此变量设置为 true。
USE_DATA_CACHING Boolean 如果当前构建对下载的文件使用 indexedDB 缓存,则此变量设置为 true。
LOADER_FILENAME String 此变量设置为构建加载程序脚本的文件名。
DATA_FILENAME String 此变量设置为主数据文件的文件名。
FRAMEWORK_FILENAME String 此变量设置为构建框架脚本的文件名。
CODE_FILENAME String 在当前构建是 WebAssembly 构建时,此变量设置为 WebAssembly 模块的文件名,否则设置为 asm.js 模块的文件名。
MEMORY_FILENAME String 当内存存储在外部文件中时,此变量设置为内存文件的文件名,否则设置为空字符串。
SYMBOLS_FILENAME String 在当前构建使用调试符号时,此变量设置为包含调试符号的 JSON 文件的文件名,否则设置为空字符串。
BACKGROUND_FILENAME String 当在 Player Settings > Splash Image 中选择了背景图像时,此变量设置为背景图像的文件名,否则设置为空字符串。

JavaScript 宏

JavaScript 宏是模板文件中的 JavaScript 代码块,由三组花括号括起。此 JavaScript 代码可以使用上面列出的内部预处理器变量。这些变量在构建时根据编辑器提供的值进行分配。在构建期间,预处理器会计算所有宏并将它们替换为变量的输出。

可以使用 JavaScript 宏预处理编辑器提供的值。这些宏可以实现任意您所需的复杂性。它们可以包含多个运算符、循环、函数和任何其他 JavaScript 结构。

以下示例行来自 Default 模板中使用的 index.html 文件:

<div id="unity-build-title">{{{ PRODUCT_NAME }}}</div>

如果 Player Settings 中 Product Name 的值设置为“My WebGL Game”,则内部预处理器变量 PRODUCT_NAME 具有值“My WebGL Game”。在输出 index.html 文件中,该行显示为:

<div id="unity-build-title">My WebGL Game</div>

下面是来自同一 index.html 模板文件的更复杂示例:

canvas.style.background = "url('" + buildUrl + "/{{{ BACKGROUND_FILENAME.replace(/'/g, '%27') }}}') center / cover";

如果目标构建文件夹名为 Let’s try WebGL,并且在 Player Settings 中选择了背景图像,则内部预处理器变量 BACKGROUND_FILENAME 具有值“Let’s try WebGL.jpg”。在输出 index.html 文件中,该行更改为:

canvas.style.background = "url('" + buildUrl + "/’Let%27s try WebGL.jpg') center / cover";

条件指令

条件指令 #if#else#endif 控制 Unity 是在输出文件中包含预处理文件的特定部分,还是在当前构建中丢弃它。

#if 指令开头并以 #endif 指令结尾的代码称为条件组。条件组还可以包含 #else 指令。Unity 会计算在 #if 后编写为 JavaScript 表达式的表达式。如果此表达式具有真值(即,在布尔值上下文中计算时转换为 true 的值),Unity 会在输出文件中保留紧跟在 #if 指令后的行组。如果 #if 表达式为 false,并且条件组中包含 #else 指令,则 Unity 会在输出中保留紧跟在 #else 指令后的行组。 条件组的示例如下所示:

# if EXPRESSION
  // 如果 EXPRESSION 具有真值,则此代码块包含在输出中
# else
  // 否则此代码块包含在输出中
# endif

计算的 JavaScript 表达式可以包含括号、逻辑运算符和其他 JavaScript 结构。条件指令可以嵌套。

自定义用户变量

选择 WebGL 模板时,Unity 会解析模板并查找 Javascript 宏和条件指令。 如果 JavaScript 变量满足以下所有条件,则它们会被视为自定义用户变量:

  • 它们在 JavaScript 宏和条件指令中进行使用。
  • 它们不在模板代码中进行声明。
  • 它们不是内部预处理器变量。

Unity 自动将这些自定义用户变量添加到 Player Settings 窗口中的 Resolution and Presentation 部分。

例如,如果要直接从 Player Settings 窗口控制生成的 index.html 页面的标题,则首先需要在自定义模板中修改 index.html&lt;title&gt; 行,如下所示: <title>{{{ PAGE_TITLE }}}</title> 完成此操作后,重新选择自定义模板。这会再次解析模板,您应该会在 Player Settings windowResolution and Presentation > WebGL Template 部分中找到 Page Title 字段。

带有自定义模板的 Resolution and Presentation 窗口图像
带有自定义模板的 Resolution and Presentation 窗口图像

在此字段中输入文本并构建项目时,模板宏中使用的自定义变量 PAGE_TITLE 会自动成为 Page Title 字段中的文本。

如果要在宏中使用自定义整数或浮点变量,请在宏中使用 parseInt()parseFloat() JavaScript 函数以预处理编辑器提供的字符串值。这是因为会始终向自定义用户变量分配字符串值。

注意:变量名称中的下划线字符在字段内会显示为空格以提高可读性。

index.html 文件的结构

index.html 包含加载构建所需的代码,应包含以下内容:

  • 一个 <canvas> 元素。Unity 运行时使用 <canvas> 元素渲染应用程序。
  • 用于下载构建加载程序的 JavaScript 代码。例如:
var buildUrl = "Build";
var loaderUrl = buildUrl + "/{{{ LOADER_FILENAME }}}";
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
  // 用于实例化构建的代码
};
document.body.appendChild(script);`

在此示例中,{{{ LOADER_FILENAME }}} 在生成构建时由模板预处理器自动解析。

或者,可以使用脚本标签下载构建加载程序,例如: lang-js <script src="Build/{{{ LOADER_FILENAME }}}"></script>

  • 用于实例化构建的 JavaScript 代码。Unity 构建使用 createUnityInstance() 函数进行实例化,该函数在构建加载程序脚本中定义。

实例化函数:createUnityInstance()

createUnityInstance() 函数为您的内容创建新实例。可以按如下所示使用它: createUnityInstance(canvas, config, onProgress).then(onSuccess).catch(onError);

此函数返回一个 Promise 对象,其中:

对象 用途
canvas Unity 运行时使用 canvas 对象渲染游戏。
config config 对象包含构建配置,例如代码和数据 URL、产品和公司名称以及版本。有关配置定义的更多信息,请参阅本页面上的构建配置部分。
onProgress(progress) {...} 每次下载进度更新时,WebGL 加载程序都会调用 onProgress 回调对象。onProgress 回调附带的 progress 参数会确定加载进度(形式为介于 0.0 与 1.0 之间的值)。
onSuccess(unityInstance) {...} 构建成功实例化之后会调用 onSuccess 回调。创建的 Unity 实例对象作为参数提供。此对象可以用于与构建交互。
onError(message) {...} 如果在构建实例化期间发生错误,则调用 onError 回调。错误消息作为参数提供。

createUnityInstance() 函数在构建加载程序脚本中定义,特定于实例化的构建。因此,如果在同一个 HTML 文档中嵌入两个或更多构建,请确保从相应构建加载程序脚本的 onload 回调中调用 createUnityInstance() 函数。有关 Unity WebGL 加载程序的更多信息,请参阅构建和运行 WebGL 项目

构建配置

配对对象包含构建配置,而构建配置由代码和数据 URL、产品名称、公司名称和版本组成。可以使用以下代码定义它:

var buildUrl = "Build";
var config = {
  dataUrl: buildUrl + "/{{{ DATA_FILENAME }}}",
  frameworkUrl: buildUrl + "/{{{ FRAMEWORK_FILENAME }}}",
  codeUrl: buildUrl + "/{{{ CODE_FILENAME }}}",
# if MEMORY_FILENAME
  memoryUrl: buildUrl + "/{{{ MEMORY_FILENAME }}}",
# endif
# if SYMBOLS_FILENAME
  symbolsUrl: buildUrl + "/{{{ SYMBOLS_FILENAME }}}",
# endif
  streamingAssetsUrl: "StreamingAssets",
  companyName: "{{{ COMPANY_NAME }}}",
  productName: "{{{ PRODUCT_NAME }}}",
  productVersion: "{{{ PRODUCT_VERSION }}}",
};

在上面的示例中,构建文件夹 URL 存储为名为 buildUrl 的单独变量。在不知道嵌入页面与托管服务器上的构建文件夹之间关系的情况下,这十分有用。它使您能够在其他 HTML 文档中重用嵌入代码。何时使用此方法的一个示例是将 Build 文件夹移动到服务器上的另一个位置的情况。可以在嵌入页面中调整 buildUrl 变量的值,并且可以使用相同的嵌入代码。这也适用于 StreamingAssets 文件夹 (streamingAssetsUrl)。

构建交互

构建成功实例化后,Promise 对象的执行处理程序回调会接收新创建的 Unity 实例对象(以参数形式)。要与构建交互,请调用 Unity 实例的以下方法:

方法 用途
unityInstance.SetFullscreen(fullscreen) SetFullscreen 方法切换全屏模式。此方法不返回值。
- 当 fullscreen 参数的值为 1 时,全屏模式会激活。*当 fullscreen 参数的值为 0 时,全屏模式会禁用。
unityInstance.SendMessage(objectName, methodName, value) SendMessage 方法向游戏对象发送消息。此方法不返回值。
- objectName 是场景中对象的名称。
- methodName 是脚本中方法的名称,当前附加到该对象。
- value 可以是字符串、数字,也可以为空。
unityInstance.Quit().then(onQuit) Quit() 方法可用于退出运行时并清理 Unity 实例使用的内存。此方法返回 Promise 对象。
- 在构建运行时退出后会调用 onQuit 回调。
构建和运行 WebGL 项目
WebGL:压缩构建和服务器配置