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 导出

参见

本页面介绍如何将 Godot 项目导出为 HTML5。如果你想要从源码编译编辑器或导出模板二进制文件,请移步《为 Web 平台编译》。

HTML5 导出允许将在 Godot 引擎中制作的游戏发布到浏览器。这需要用户浏览器支持 WebAssemblyWebGL 2.0

注意

使用 Godot 4 以 C# 编写的项目目前无法导出到 Web。更多信息请参阅这篇博客

要在 Web 平台上使用 C#,请使用 Godot 3。

小技巧

使用浏览器集成的开发者控制台,通常通过 F12Ctrl + Shift + I(macOS 上为 Cmd + Option + I)打开,以查看调试信息,如 JavaScript、引擎和 WebGL 错误。

如果快捷键不起作用,这是因为 Godot 捕获了输入。你仍然可以通过访问浏览器的菜单来打开开发者控制台。

备注

由于 SharedArrayBuffer 存在各种安全漏洞,在 Web 平台上使用多线程有一些缺点,包括需要特定的服务器端头文件和完全的跨域隔离(这意味着托管你游戏的网站上不能有广告,也不能有第三方集成)。

自 Godot 4.3 起,Godot 支持以单线程导出你的游戏,这解决了这个问题。虽然它本身有一些缺点(不能使用线程,性能不如多线程导出),但它不需要那么多的安装开销。它总体上与 itch.io 等商店或 PokiCrazyGames 等网页发布商更兼容。单线程导出在 macOS 和 iOS 上也运行得很好,这些平台在多线程导出时总是存在兼容性问题。

出于这些原因,这是在 Web 上导出游戏的推荐方式,也是目前的默认方式。

如需了解更多信息,请参阅这篇关于单线程 Web 导出的博客文章

参见

参见 GitHub 上与 Web 导出相关的公开问题列表了解已知的漏洞。

导出文件名

我们建议用户导出 Web 项目时使用 index.html 作为文件名。index.html 通常是 Web 服务器访问父目录时默认加载的文件,通常会隐藏该文件的名称。

注意

Godot 4 的 Web 导出要求某些文件的名称与初始导出时设置的文件名保持一致。如果重命名了某些导出的文件(包括主 HTML 文件),可能会导致一些问题。

WebGL 版本

Godot 4 只能以 WebGL 2.0 为目标(使用 Compatibility 渲染方法)。Web 平台不支持 Forward+/Mobile 渲染方法,因为这些渲染方法是围绕现代低级图形 API 设计的。Godot 目前不支持 WebGPU,而这是让 Forward+/Mobile 在 Web 平台上运行的前提条件。

支持 WebGL 2.0 的浏览器版本列表见我能使用 WebGL 2.0 吗。请注意,Safari 对 WebGL 2.0 的支持存在很多问题,这些问题在其他浏览器中并不存在,因此我们推荐尽量使用基于 Chromium 的浏览器或 Firefox。

移动设备注意事项

Web 导出可以在移动平台上运行,但有一些注意事项。虽然原生的 AndroidiOS 导出的性能会显著更好,但 Web 导出允许用户无需通过应用商店即可运行你的项目。

请记住,在移动设备上运行时,CPU 和 GPU 的性能非常宝贵。当运行导出到 Web 的项目时(因为它是 WebAssembly 而非原生代码),这一点尤为重要。有关优化项目的建议,请参阅文档的性能部分。如果你的项目运行在 Web 以外的平台上,你可以使用功能标签来在运行导出到 Web 的项目时应用面向低端设备的设置。

为了加速移动设备上的加载,你还应该编译一个经过优化且禁用未使用功能的导出模板。根据项目所使用的功能,这可以显著减小 WebAssembly 有效载荷的大小,使其下载和初始化速度更快(即使已被缓存)。

音频回放

自 Godot 4.3 起,网页平台上的音频播放使用 Web Audio API 实现。这种 Sample 播放模式即使在项目导出时不支持线程的情况下也能实现低延迟,但它有几个限制:

  • 不支持 AudioEffect。

  • 不支持混响和多普勒效果

  • 不支持程序式音频生成。

  • 根据节点的属性,位置音频可能无法始终正常工作。

要在网页平台上使用 Godot 自带的音频播放系统,你可以通过音频 > 常规 > 默认播放类型.web 项目设置来更改默认的播放模式,或者将 AudioStreamPlayerAudioStreamPlayer2DAudioStreamPlayer3D 节点的播放类型属性更改为 Stream。这会导致延迟增加(尤其是在禁用线程支持的情况下),但它允许 Godot 的全部音频功能正常工作。

导出选项

如果可以使用可运行的 Web 导出模板,则编辑器中的停止场景播放编辑的场景按钮之间会出现一个按钮,可以在默认浏览器中快速打开游戏进行测试。

如果你的项目使用 GDExtension,则需要启用扩展支持

如果你打算使用 VRAM 压缩,请确保为目标平台启用 VRAM 纹理压缩(同时启用对桌面平台对移动平台将导致更大,但更兼容的导出)。

如果给出了自定义 HTML Shell 文件的路径,则将使用它来代替默认的 HTML 页面。请参阅用于 Web 导出的自定义 HTML 页面

Head Include 被附加到生成的 HTML 页面的 <head> 元素中。例如,这允许加载 webfonts 和第三方 JavaScript API,包含 CSS 或运行 JavaScript 代码。

窗口大小默认自动匹配浏览器窗口。如需固定尺寸,请将画布缩放策略设为,此时可通过 HTML shell 中的自定义 JavaScript 代码控制窗口尺寸。也可设为项目,使其行为更接近原生导出(遵循项目设置)。

重要

每个项目必须生成自己的 HTML 文件。导出时,生成的 HTML 文件中的文本占位符会根据给定的导出选项进行替换。任何对该 HTML 文件的直接修改都会在后续的导出中丢失。要自定义生成的文件,请使用自定义 HTML Shell 选项。

线程及扩展支持

如果启用了线程支持,导出的项目将能够利用多线程来提高性能。当播放类型设置为 Stream(而不是 Web 导出中使用的默认 Sample)时,这也允许低延迟的音频播放。启用此功能需要使用跨域隔离标头,这些标头在下面的提供文件部分中有详细说明。

如果启用了扩展支持,将能够加载 GDExtensions。请注意,GDExtensions 仍然需要专门为 Web 平台编译才能正常工作。与线程支持类似,启用此功能需要使用跨域隔离标头。

导出为渐进式 Web 应用(PWA)

启用渐进式网络应用程序 > 启用将会产生以下影响:

  • 配置高分辨率图标、显示模式和屏幕方向。这些设置在导出选项的渐进式 Web 应用(Progressive Web App)部分的末尾进行配置。当用户将项目添加到设备的主屏幕时(这在移动平台上很常见),会使用这些选项。桌面平台也支持这些功能,但功能相对有限。

  • 允许项目在没有网络连接的情况下加载,前提是该项目之前至少加载过一次。这要归功于首次在用户浏览器中加载项目时安装的 service worker。当没有网络连接时,该 service worker 会提供一个本地回退方案。

    • 请注意,如果用户的磁盘空间不足,或者用户有一段时间没有打开项目,浏览器可能会选择清除缓存数据。为了确保数据能够缓存更长时间,用户可以收藏该页面,或者最好是将其添加到设备的主屏幕上。

    • 如果由于缓存被清除导致离线数据不可用,你可以配置一个离线页面在这种情况下显示。该页面必须是 HTML 格式,并且会在项目首次加载时保存在客户端机器上。

  • 确保始终存在跨域隔离标头,即使 Web 服务器未配置为发送这些标头。这使得启用线程的导出可以在任何网站上托管时正常工作,即使你无法控制其发送的标头。

    • 这种行为可以通过在渐进式 Web 应用部分取消勾选启用跨域隔离标头来禁用。

限制

出于安全和隐私的原因,许多在本机平台上轻松工作的功能在 Web 平台上更加复杂。以下列出了将 Godot 游戏移植到 Web 时应注意的限制。

重要

浏览器供应商正在使越来越多的功能只在安全上下文中可用,这意味着这些功能只有在通过安全的 HTTPS 连接提供网页时才可用(localhost 通常不受这种要求影响)。

使用 cookie 进行数据持久化

如果需要持久化 user:// 文件系统,用户必须允许 cookie(特别是 IndexedDB)。当游玩用 iframe 呈现的游戏时,还必须启用第三方 cookie。隐身/隐私浏览模式也会阻止持久化。

方法 OS.is_userfs_persistent() 可用于检查 user:// 文件系统是否持久,但在某些情况下会误报。

后台处理

当标签页不再是用户浏览器的活动标签页时,项目就会被浏览器暂停。这意味着 _process()_physics_process() 等函数将不再运行,直到用户再次激活该标签页(切换回该标签页)。如果用户在标签页外停留了过长的时间,就可能造成网络游戏的掉线。

这一限制不适用于丢失焦点的浏览器窗口。因此,对于用户而言,变通方法是让项目运行在一个单独的窗口中,而不是标签页。

全屏和鼠标捕获

浏览器不允许任意进入全屏捕获光标也是如此。这些操作只能在响应 JavaScript 输入事件时进行。在 Godot 中,这意味着需要在 _input_unhandled_input 等输入事件回调中进入全屏。查询Input单例并不满足这一条件,相关的输入事件必须处于活动状态。

出于同样的原因,除非从有效的输入事件处理程序中启动引擎,否则全屏项目设置将不起作用。这需要定制 HTML 页面

音频

一些浏览器限制网站上的音频自动播放。绕过这一限制的最简单方法是请求玩家点击、点击或按下一个键/按钮以启用音频,例如在游戏开始时显示启动屏幕时。

参见

Google 提供了有关其网络音频自动播放政策的其他信息。

苹果的 Safari 团队也针对他们对 macOS 自动播放策略的调整发布了额外说明。

警告

访问麦克风需要安全上下文

警告

自 Godot 4.3 起,Web 导出默认将使用 samples 而非 streams 来播放音频。

这是由于浏览器播放音频的方式以及在使用 Use Threads(使用线程)导出选项关闭时,导出 Web 游戏可用的处理能力不足所导致的。

请注意,音频效果尚未在 samples 中实现。

网络

由于缺乏浏览器的支持,低级别的网络功能没有实现。

目前,只有 HTTP 客户端HTTP 请求WebSocket (客户端)WebRTC 受支持。

HTTP 类在 HTML5 平台上也有若干限制:

  • 无法访问或更改 StreamPeer

  • Threaded/Blocking 模式不可用

  • 每帧不能进行多次,因此循环中的轮询将冻结

  • 没有分块响应

  • 无法禁用主机验证

  • 遵循同源政策

剪贴板

在引擎和操作系统之间同步剪贴板需要浏览器支持剪贴板 API,此外,由于该 API 的异步性,从 GDScript 访问时可能不可靠。

警告

需要安全上下文

游戏手柄

按下游戏手柄上面的任一按钮之后,这个游戏手柄才能被检测到。根据浏览器、操作系统、游戏手柄三者的组合不同,游戏手柄的映射可能有误,可惜由于隐私方面的考虑,游戏手柄 API 并没有提供可靠的方法来检测游戏手柄的信息,因而无法根据模型、供应商、操作系统来进行重新映射。

警告

需要安全上下文

提供文件

Web 导出会生成多个要通过 Web 服务器提供的文件,包括用于演示的默认 HTML 页面。可以使用自定义 HTML 文件,请参阅用于 Web 导出的自定义 HTML 页面

警告

仅在导出时启用 Use Threads(使用线程)的情况下,为了确保较低的音频延迟和在 Web 导出中使用 Thread 的能力,Godot 4 Web 导出使用 SharedArrayBuffer。这需要一个安全上下文,同时还需要在提供文件时设置以下 CORS 标头:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

如果你无法控制 Web 服务器或无法添加响应头,请在导出选项中勾选渐进式网络程序 > 启用。这将应用一个基于 Service Worker 的解决方案,通过模拟这些响应头的存在来允许项目运行。在这种情况下,仍然需要一个安全上下文。

客户端收不到必要的响应报头,项目就不会运行

生成的 .html 文件可以在 Apache 服务器中用作 DirectoryIndex,文件名可以随便修改,比如可以改成 index.html。默认情况下不会用到这个名称。

HTML 页面在浏览器窗口内以最大尺寸绘制游戏。这样,就可以将其插入游戏大小的 <iframe> 中,这在大多数网络游戏托管站点中很常见。

其他导出的文件在 .html 文件旁边,按原样提供,名称不变。.wasm 文件是实现引擎的二进制 WebAssembly 模块。.pck 文件是包含你的游戏的 Godot 主包。.js 文件包含启动代码,.html 文件使用它来访问引擎。.png 文件包含启动画面图像。

.pck 文件是二进制文件,通常与 MIME 类型 application/octet-stream 一起分发。.wasm 文件以 application/wasm 分发。

警告

分发 WebAssembly 模块(.wasm)时,使用一个 application/wasm 以外的 MIME 类型,可能会阻止某些启动优化。

建议使用服务器端压缩来分发文件,特别是 .pck.wasm 文件,因为这种文件通常很大。WebAssembly 模块的压缩做得特别好,使用 gzip 压缩最多能够缩小到原始大小的四分之一左右。如果 Web 服务器支持的话,请考虑使用 Brotli 预压缩,能够进一步节省文件大小。

提供即时压缩的主机: GitHub Pages(gzip)

不提供即时压缩的主机:itch.io,GitLab 页面(支持手动 gzip 预压缩

小技巧

Godot 的仓库中包含了一个用来运行本地 Web 服务器的 Python 脚本。这个脚本原本是用于测试 Web 编辑器的,但也可以用来测试导出后的项目。

将链接中的脚本保存为 serve.py 文件,将这个文件移动到包含导出后项目的 index.html 的文件夹中,然后在该文件夹中打开命令提示符,执行以下命令:

# You may need to replace `python` with `python3` on some platforms.
python serve.py --root .

在 Windows 上,你可以通过按住 Shift 并右键点击 Windows 资源管理器中的空白区域,然后选择在此处打开 PowerShell 窗口,在当前文件夹中打开命令提示符。

这将提供目前文件夹的内容并自动开启预设的 Web 浏览器。

请注意,对于生产用例,不应使用此基于 Python 的 Web 服务器。相反,你应该使用已建立的 Web 服务器,例如 Apache 或 nginx。

与浏览器和 JavaScript 交互

请参阅专用页面以了解如何与 JavaScript 交互并访问一些独特的 Web 浏览器功能。

环境变量

你可以使用以下环境变量在编辑器外部设置导出选项。在导出过程中,这些值会覆盖你在导出菜单中设置的值。

HTML5 导出环境变量

导出选项

环境变量

加密 / 密钥

GODOT_SCRIPT_ENCRYPTION_KEY

故障排除

本地运行导出却显示了其他项目

如果你在多个项目中使用一键部署功能,可能会发现显示的是之前部署过的某个项目,而非当前正在处理的项目。这是由于服务工作线程(service worker)缓存所致,目前尚无自动缓存清除机制。

作为临时解决方案,您可以手动注销当前的服务工作线程(service worker),以重置缓存,从而允许注册新的服务工作线程。在基于 Chromium 的浏览器中,按 F12Ctrl + Shift + I(macOS 上为 Cmd + Option + I)打开开发者工具,然后点击 DevTools 中的“Application”(应用程序)标签页(如果开发者工具窗格较窄,该标签可能隐藏在右上角的“>”图标后)。您可以勾选 Update on reload(重新加载时更新)并刷新页面,或点击当前已注册服务工作线程旁边的 Unregister(注销)按钮,然后重新加载页面。

在基于 Chromium 的浏览器的开发者工具中注销服务工作线程

在基于 Chromium 的浏览器的开发者工具中注销服务工作线程

Firefox 中的操作步骤类似。按 F12Ctrl + Shift + I(macOS 上为 Cmd + Option + I)打开开发者工具,点击 DevTools 中的“Application”(应用程序)标签页(如果开发者工具窗格较窄,该标签可能隐藏在右上角的“>”图标后)。点击当前已注册服务工作线程旁边的 Unregister(注销)按钮,然后重新加载页面。

在 Firefox 的开发者工具中注销服务工作线程

在 Firefox 的开发者工具中注销服务工作线程

导出选项

导出选项的完整列表见 EditorExportPlatformWeb 类参考文档。