Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

用于 Web 导出的自定义 HTML 页面

虽然 Web 导出模板提供了一个默认的 HTML 页面,完全能够在无需进一步定制的情况下启动项目,但创建自定义 HTML 页面可能更有益。虽然游戏本身目前还无法从外部直接控制,但这样的页面允许自定义引擎的初始化过程。

自定义默认页面在以下情况非常有用:

  • 从与该页面不同的目录加载文件;

  • .zip 文件而不是 .pck 文件作为主资源包加载;

  • 从与主资源包文件不同的目录加载引擎;

  • 添加“点击开始”按钮,使游戏可以在全屏模式下启动;

  • 在引擎启动之前加载一些额外的文件,使其在文件系统中尽快可用;

  • 传递自定义命令行参数,例如 -s 以启动 MainLoop 脚本。

默认的 HTML 页面可在 Godot 引擎仓库的 /misc/dist/html/full-size.html 找到,但以下模板可作为一个更简单的例子:

<!DOCTYPE html>
<html>
    <head>
        <title>My Template</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <canvas id="canvas"></canvas>
        <script src="$GODOT_URL"></script>
        <script>
            var engine = new Engine($GODOT_CONFIG);
            engine.startGame();
        </script>
    </body>
</html>

设置

如上面的例子所示,它主要是一个普通的 HTML 文档,有几个占位符需要在导出时替换,一个 HTML <canvas> 元素,以及一些简单的 JavaScript 代码用于调用 Engine() 类。

唯一必需的占位符是:

  • $GODOT_URL:主 JavaScript 文件的名称,它提供了启动引擎所需的 Engine() 类,必须作为 <script> 包含在 HTML 中。该名称是在导出过程中根据导出路径生成的。

  • $GODOT_CONFIG:一个 JavaScript 对象,包含导出选项,以后可以被重写。参见 EngineConfig 获取完整的可重写选项列表。

以下可选占位符将在你的自定义 HTML 模板中启用一些额外功能。

  • $GODOT_PROJECT_NAME:在项目设置 > 应用 > 配置中的名称设置中定义的项目名称。在模板中将其用作 <title> 是个好主意。

  • $GODOT_HEAD_INCLUDE:要在 HTML 文档中包含的自定义字符串,位于 <head> 标签结束之前。它在导出选项的 HTML / 头部包含部分中自定义。虽然你本就可以完全控制所创建的 HTML 页面,但这个变量对于从 Godot 编辑器中配置 HTML head 元素的部分内容很有用,例如针对不同的 Web 导出预设。

  • $GODOT_SPLASH:启动画面图像的路径,该图像在项目设置 > 应用 > 启动画面中的图像设置中定义。

  • $GODOT_SPLASH_COLOR:启动画面背景颜色,该颜色在项目设置 > 应用 > 启动画面中的背景颜色设置中定义,并转换为十六进制颜色代码。

  • $GODOT_SPLASH_CLASSES:该占位符提供一个包含设置名称及其值的字符串,这些设置会影响启动画面。该字符串旨在用作一组 CSS 类名,允许根据启动画面的项目设置来设置启动图像的样式。以下设置来自项目设置 > 应用 > 启动画面,根据设置的布尔值,由以下类名表示:

自定义页面准备好后,可以在导出选项的 HTML / 自定义 HTML Shell 部分中选择它。

../../../_images/html5_export_options.png

启动项目

要启动游戏,你需要编写一个脚本来初始化引擎——即控制代码。该过程包含三个步骤,但正如这里所示,根据所需的自定义程度,其中大部分步骤可以跳过。

有关可用方法和选项的完整列表,请参见HTML5 shell 类参考

首先必须加载引擎,然后需要初始化它,之后才能启动项目。你可以手动执行这些步骤中的每一步并进行精细控制。然而,在最简单的情况下,你需要做的只是用导出的配置创建一个 Engine() 类的实例,然后调用 engine.startGame 方法,同时可选择重写任何 EngineConfig 参数。

const engine = new Engine($GODOT_CONFIG);
engine.startGame({
    /* optional override configuration, eg. */
    // unloadAfterInit: false,
    // canvasResizePolicy: 0,
    // ...
});

这段代码会在启动游戏之前自动加载并初始化引擎。它使用给定的配置来加载引擎。engine.startGame 方法是异步的,并返回一个 Promise。这允许你的控制代码跟踪游戏是否已正确加载,而无需阻塞执行或依赖轮询。

如果你的项目需要对启动参数和依赖文件进行特别控制,可以使用 engine.start 方法来代替。注意,这个方法不会自动预加载 pck 文件,所以你可能需要通过 engine.preloadFile 方法手动预加载它(以及任何其他额外文件)。

另外,你也可以手动调用 engine.init,在模块初始化之后、引擎启动之前执行特定的动作。

这个过程稍微复杂一些,但可以让你完全控制引擎的启动过程。

const myWasm = 'mygame.wasm';
const myPck = 'mygame.pck';
const engine = new Engine();
Promise.all([
    // Load and init the engine
    engine.init(myWasm),
    // And the pck concurrently
    engine.preloadFile(myPck),
]).then(() => {
    // Now start the engine.
    return engine.start({ args: ['--main-pack', myPck] });
}).then(() => {
    console.log('Engine has started!');
});

要手动加载引擎,必须调用 Engine.load() 静态方法。由于这个方法是静态的,如果多个引擎实例共享相同的 wasm,就可以生成多个实例。

备注

默认情况下无法生成多个实例,因为引擎在初始化后会立即卸载。要防止这种情况发生,请参见 unloadAfterInit 覆盖选项。之后仍然可以通过调用 Engine.unload() 静态方法来手动卸载引擎。卸载引擎会通过卸载实例初始化后不再需要的文件来释放浏览器内存。

自定义行为

在 Web 环境下,可以使用几种方法来保证游戏能够按预期运行。

如果你的目标是特定版本的 WebGL,或者只是想检查 WebGL 是否可用,可以调用 Engine.isWebGLAvailable() 方法。它接受一个可选参数,用于测试特定的主版本号。

由于真正的可执行文件在 Web 环境中并不存在,引擎只存储一个由加载的引擎文件的主名称形成的虚拟文件名。这个值会影响 OS.get_executable_path() 方法的输出,并定义自动启动的主包的名称。executable 覆盖选项可用于重写这个值。

自定义表现形式

可以使用几个配置选项来进一步定制页面上游戏的外观和行为。

默认情况下会使用页面上的第一个 canvas 元素渲染。要使用其他 canvas 元素,可以使用 canvas 覆盖选项。它需要对该 DOM 元素本身的引用。

const canvasElement = document.querySelector("#my-canvas-element");
engine.startGame({ canvas: canvasElement });

引擎调整 canvas 大小的方式可以通过 canvasResizePolicy 覆盖选项进行配置。

如果你的游戏需要一些时间来加载,显示一个跟踪进度的自定义加载 UI 可能很有用。这可以通过 onProgress 回调选项来实现,它允许设置一个回调函数,当引擎加载新字节时定期调用该函数。

function printProgress(current, total) {
    console.log("Loaded " + current + " of " + total + " bytes");
}
engine.startGame({ onProgress: printProgress });

请注意,在某些情况下 total 可能是 0。这意味着无法计算。

如果你的游戏支持多种语言,locale 覆盖选项可用于强制使用特定的语言区域,前提是你有一个有效的语言代码字符串。最好使用服务器端逻辑来确定用户可能偏好的语言。此时,语言代码可以从 Accept-Language HTTP 头中获取,或者由 GeoIP 服务决定。

调试

要调试导出的项目,读取引擎生成的标准输出和错误流可能很有用。这与编辑器控制台窗口中显示的输出类似。默认情况下,标准的 console.logconsole.warn 分别用于输出流和错误流。这种行为可以通过设置自己的函数来处理消息进行定制。

使用 onPrint 覆盖选项为输出流设置回调函数;使用 onPrintError 覆盖选项为错误流设置回调函数。

function print(text) {
    console.log(text);
}
function printError(text) {
    console.warn(text);
}
engine.startGame({ onPrint: print, onPrintError: printError });

处理引擎输出时,请记住,在成品中打印输出可能并不可取。