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.

导出包、补丁、模组

使用案例

很多时候,人们希望在游戏部署后为它添加功能。

这样的例子包括……

  • 可下载内容:向游戏添加功能和内容的能力。

  • 补丁:修复已发布产品中存在的错误的能力。

  • 模组(mod):授予其他人为自己的游戏创建内容的能力。

这些工具可帮助开发人员基于初始版本进行扩展开发。

PCK/ZIP 文件概述

Godot 通过资源包实现此功能(扩展名为 .pck 的 PCK 文件或 ZIP 文件)。

优势:

  • 增量更新/补丁

  • 提供 DLC

  • 提供模组支持

  • 模组不需要公开源代码

  • 更加模块化的项目结构

  • 用户无需替换整个游戏

使用此方法时,首先需要将项目导出并交付给玩家。之后若想添加功能或内容,只需通过 PCK/ZIP 文件将更新交付给用户即可。

PCK/ZIP 文件通常包含但不限于:

  • 脚本

  • 场景

  • 着色器

  • 模型

  • 纹理

  • 音效

  • 音乐

  • 任何其他适合导入游戏的资产

PCK/ZIP 文件甚至可以是一个完全不同的 Godot 项目,由原始游戏在运行时加载。

PCK 和 ZIP 文件可同时作为附加资源包加载。两种格式对比详见PCK 与 ZIP 打包文件格式对比

参见

若需在运行时加载松散文件(非 Godot 打包的 PCK/ZIP),建议改用运行时文件加载和保存。此方案适用于加载非 Godot 生成的用户内容,无需用户将模组打包为特定格式。

此方案的缺点是游戏逻辑的透明度较低,因为无法享受与 PCK/ZIP 文件相同的资源管理机制。

安全问题

需要特别注意的是,如果通过加载 PCK 文件来实现游戏补丁、模组(Mods)或扩展包等额外内容,你就需要自己编写一套系统,来根据文件的位置(可能还包括文件名)自动加载它们。这种做法在三种情况下会带来安全漏洞:第一,用户下载了包含恶意代码的模组;第二,用户的电脑上已经存在恶意程序,并且该程序用恶意的 PCK 文件替换了原本正常的文件;第三,你通过游戏启动器分发补丁 PCK 文件,但该分发系统本身遭到了入侵或破坏。

在决定如何在项目中使用 PCK 文件时,请务必将这一点纳入考量。如果是通过启动器来分发补丁的情况,建议考虑使用非对称加密技术。你可以将公钥(public key)存储在主 PCK 文件中,然后使用私钥(private key)对补丁或扩展包的 PCK 文件进行数字签名。更多详细信息,请参阅 Crypto 的相关文档。

生成 PCK 文件

为了将项目的所有资源打包到 PCK 文件中,请打开项目,进入 Project > Export,选择一个导出预设,然后点击 Export PCK/ZIP

../../_images/export_pck.webp

另一种方法是从命令行导出并添加 --export-pack 参数。输出文件必须具有 .pck.zip 文件扩展名。导出过程将根据所选平台生成相应类型的文件。

PCK 补丁文件

生成 PCK 补丁文件

如果你想创建一个只包含项目初始版本中不存在的资源的 PCK 文件,你需要制作一个‘补丁 PCK 文件’(patch PCK file)。这种文件非常适合用来发布游戏补丁、模组(Mods)或者扩展包。为了实现这一点,你首先需要拥有项目在最初发布时的 PCK 文件(作为基础)。

要生成一个补丁 PCK 文件,请在导出菜单中(确保已经选中了你想要的预设),点击 Patching 选项卡。在底部你会看到 Base Packs 区域。点击 Add Pack 按钮,然后找到并选中你最初发布游戏时导出的那个包含了所有项目资源的 PCK 文件。

现在,当你再次导出项目的 PCK 文件时,只要你勾选了 Export as Patch 这个按钮,那么导出的 PCK 文件中就只会包含那些发生过改变的资源。

你也可以把任何已经导出的补丁添加到你的基础包列表中,以便后续使用。举个例子,如果你把 patch.pck 也加进基础包里,就能确保你之后导出的 patch2.pck 里,不会重复包含第一个补丁里的任何资源。

增量编码

通过使用增量编码(delta encoding)技术,可以让补丁 PCK 文件变得更小。它的原理是,只更新文件中实际发生过改动的那部分数据。不过,这种做法也有一个缺点,那就是被更新的资源加载时间会变长;而且,针对同一个资源的每一个补丁,其加载时间还会不断累积叠加。

除了过滤器(filters)之外,增量编码还有两个可供调整的设置选项:

  • 增量编码压缩级别(Delta Encoding Compression Level): 控制对文件应用的压缩程度。我们不建议将数值设置得超过默认值 19。如果超过这个数值,不仅需要消耗更多的内存来进行导出和导入,而且带来的收益(体积减小)也会显著降低。任何正值在解压时的速度都是相同的,不过数值越高,导出所花费的时间就会越长。负值则会启用‘快速模式(fast mode)’,这意味着导出的文件体积会更大,但解压速度会更快。

  • 增量编码最小体积缩减率(Delta Encoding Minimum Size Reduction): 用来控制单个文件必须至少节省多少空间,才会真正对它启用压缩。举个例子,如果将这个值设定为 10%,而某个文件经过计算后发现只能缩减 5% 的体积,那么这个文件就不会使用增量编码(而是直接按原样打包)。

默认的压缩级别 19,是官方推荐使用的最高级别。

如果想要让补丁的体积尽可能小,我们建议对你想要打补丁的所有资源关闭压缩。即使你最初的基础 PCK 文件是开启了压缩的,这样做也不会引发任何问题。

你可以在以下几个不同的地方,为不同类型的资源分别关闭压缩:

  • 针对单独导入的资源(比如翻译文件或 3D 模型文件),可以在它们的导入设置(Import settings)中找到并关闭相关的压缩选项

  • Compress Binary Resources 在编辑器设置

  • 导出预设(export preset)中 Scripts 选项卡下的 GDScript Export Mode

备注

在关闭 Compress Binary Resources 选项后,你必须先删除项目里 .godot/imported/ 文件夹中的所有内容,然后完全关闭并重新打开该项目,以便让引擎重新生成这些文件。

需要特别注意的是,如果你要在已有的补丁基础上,继续导出新的增量补丁,那么你在导出预设的 Patching 选项卡下的 Base Packs 列表中列出的文件,必须与游戏在运行时实际加载的文件完全一致,并且加载的先后顺序也必须完全相同。由于 Godot 的导出过程存在一定的不确定性(non-determinism),如果你重新导出旧版本的游戏,生成的文件可能会和原版有细微的差别,这就会导致后续的增量补丁生成失败。这个问题仅存在于增量编码补丁中,普通的完整补丁不会遇到这种情况。

在运行时打开 PCK 或 ZIP 文件

PCK 和 ZIP 文件的加载需要用到 ProjectSettings 单例。下面的例子需要在游戏可执行文件所在目录中存在 mod.pck 文件。该 PCK 或 ZIP 文件的根目录中包含一个 mod_scene.tscn 测试场景。

func _your_function():
    # This could fail if, for example, mod.pck cannot be found.
    var success = ProjectSettings.load_resource_pack(OS.get_executable_path().get_base_dir().path_join("mod.pck"))

    if success:
        # Now one can use the assets as if they had them in the project from the start.
        var imported_scene = load("res://mod_scene.tscn")

警告

默认情况下,如果导入的文件与项目中已有的文件具有相同的文件路径和名称,则导入的文件将替换它。创建 DLC 或模组时需要注意这一点,可以使用工具将模组隔离到特定模组子文件夹来解决此问题。

但这也是为游戏创建补丁的一种方式。此类 PCK/ZIP 文件可覆盖先前加载的 PCK/ZIP 内容(因此包的加载顺序有影响)。

如需禁用此行为,请将 false 作为第二个参数传递给 ProjectSettings.load_resource_pack()

备注

对于 C# 项目,你必须先构建 DLL 并把它放在项目目录中。然后,在加载资源包之前,你需要用以下方法加载它的 DLL:Assembly.LoadFile("mod.dll")

故障排除

若加载资源包后观察不到任何变化,这可能是因为加载顺序过晚。这种问题尤其出现在经常使用 preload() 预加载其他场景的菜单场景。也就是说在菜单中加载资源包不会影响已预加载的场景。

为避免此问题,需尽早加载资源包。具体方法:创建自动加载脚本,并在其 _init() 函数(而非 _enter_tree()_ready())中调用 ProjectSettings.load_resource_pack()

模组(Mod)制作注意事项

如果你希望自己的游戏支持模组(Mod),就需要让玩家也能制作并导出类似的文件。前提是,原版游戏对 PCK 文件内的资源结构,和/或脚本的接口有一定的规范,那么接下来就必须完成以下两件事中的一件。

  1. 开发者必须将这些预期的结构记录在文档中/

    (开发者需要开放)接口,并要求模组(Mod)作者安装 Godot 引擎。同时,还要要求这些模组作者在制作游戏内容时,必须严格遵循文档中定义的 API 规范(这样才能确保 Mod 正常运行)。随后,用户(模组作者)就需要使用 Godot 自带的导出工具,来生成上文提到的 PCK 文件。

  2. 开发者使用 Godot 来构建一个 GUI 工具,用于添加他们特定的 API

    内容整合到项目中。这个 Godot 工具必须运行在一个启用了 tools(编辑器功能)的引擎版本上,或者能够访问到这样一个版本(比如随工具一起分发,或者放在原版游戏的文件里)。然后,该工具就可以通过命令行,利用 Godot 可执行程序配合 OS.execute() 来导出一个 PCK 文件。出于安全考虑,游戏本体不应该使用启用了 tools 的引擎版本来运行,所以最好是将模组制作工具与游戏本体分开存放。