Blender Studio 开展游戏项目的核心目标之一是验证并熟悉开源游戏开发的现状。由于我们决定使用 Godot 作为引擎(当然,Blender 也作为我们的 DCC),我们必须围绕这两个工具建立一个流程,以便一个八人团队能够处理游戏文件。 在本文中,我将概述我们的想法。
从项目伊始,我们就构思了一个理想的流程。其中一个挑战是,我们的工作室是为电影制作而设立的。我们的工具、基础设施和团队的技能组合都面向电影制作。我们越是坚持自己熟悉的领域,就越能取得更好的成果。
理想情况下,我们能够尽可能多地利用 Blender,并建立一个流程,使我们能够在 Blender 中进行资源创建、场景组装、动画库以及基本的游戏特定定义(例如碰撞)。 Godot 真正被触及的地方,只有验证游戏内的实际效果时才会用到(当然,除了实现整个游戏逻辑之外)。
为了实现这一点,我们需要能够在 Blender 中预览资源在游戏中的实际效果。由于我们大部分时间都采用标准的 PBR 工作流程,因此开箱即用,效果非常好。
这种以 DCC 为中心的工作流程在游戏开发中并不常见。但对我们来说,这是一种正确的方法,让我们能够充分发挥自己的优势。
为了使我们的资源在游戏文件中可用,我们选择了 glTF 作为交换格式。这对我们来说是一个显而易见的选择,原因如下:
Godot 也支持直接导入 .blend 文件,但我们决定不使用它。直接导入资源意味着没有明确的导出/发布步骤。因此,工作文件和游戏资源文件之间没有区别。这通常可以行得通,但在多人协作时,我们发现明确地将更改推送到生产环境中会很有用。
由于 Godot 的这个功能本身就使用 glTF 作为交换格式,因此将导出步骤明确地纳入我们的流程并让我们更好地控制该流程是一个更好的解决方案。
自动化导出流程的一个关键方面是使用 Blender 的导出集合功能。这意味着我们可以设置专用集合来导出多个单独的资源,而无需导出整个文件。因此,所有资源的导出设置都可以提前设置,并且可以一次性单独导出文件中的所有资源。
它还允许将各种附加数据保存在 .blend 文件中以供参考,而不会污染导出数据。
棘手的部分在于如何实现资源的嵌套,而不会重复导出嵌套资源。这就是一些额外自定义代码的用武之地。
为了赋予我们必要的控制权,使美术团队能够轻松地将资源发送到 Godot 并从 Blender 中进行迭代,我们在两端都编写了自定义代码。
Blender 有一个扩展,可以处理资源的设置和导出,并提供所有必要的信息。此外,还有一个 Godot 插件,可以确保每次导入时,使用提供的数据正确地重新创建资源并生成所需的游戏数据。
您可以在本文末尾找到该代码的(非常)初步版本,这对我们来说已经足够好了,但还不是一个完整的工具。
设置的一个核心原则是,美术师导出到游戏文件的每个资源都只包含其自身的直接数据。如果其中嵌套了其他资源(例如集合实例),则应将其替换为引用,并在导入时在 Godot 中重新创建该引用。
这样,树资源及其各个部分就可以在一个文件中定义(可能每个分支都有一个资源集合),并且树的实例化和位置可以在单独的设置文件中定义。集合、树和分支都是独立的资源,每个资源的数据只导出一次,并且 .blend 文件之间存在的引用会在 Godot 中的导出文件之间重新创建。在这种情况下,设置资源实际上只包含其他资源的引用和变换。
我们的实际工作流程如下:
以下是场景设置流程的简要概述:
以及更详细的分解:
我们有不同类型的资源,需要根据项目的具体导出设置进行选择。这些类型包括角色、资源和动画。
为了能够以正确的设置导出到正确的位置,导出扩展程序中有一个初始化按钮,可以自动设置集合导出器的输出路径和所有其他设置。对于任何工作文件,艺术家只需按下初始化按钮,即可导出。这仅仅依赖于使用正确的命名约定。
{附件 10720} 初始化一个库文件,其中包含多个嵌套的库资源,这些资源的集合名称以“LI-”为前缀。
包含“.blend”文件的工作目录结构和包含 glTF 导出文件的游戏文件是两个独立的文件结构,它们基本上是彼此的副本。
每次导出之前,Blender 扩展程序都会处理一些必要的事项:
.json 文件中,以便在 Godot 中通过 ID 找到它。导出后,扩展程序会将数据重置为可用状态,以便恢复实例化数据。
导出材质所使用的纹理也会移动到游戏文件目录中正确的相对路径,以确保重复使用相同纹理的资源不会在整个项目中重复使用。
这一切都是使用一些基本的导出钩子完成的,导出过程会自动运行。
关于许多可用导出钩子的信息,可以在这里找到。(https://github.com/KhronosGroup/glTF-Blender-IO/tree/main/example-addons/example_gltf_exporter_extension)%E3%80%82
导入过程完全自动化。Godot 会自动检测资源是否发生变化,并导入新的/更改的文件。
每次发生这种情况时,都必须运行确保数据正确导入的代码。
导入插件最重要的任务是:
最终,我们得到了一个 .tscn 文件的层级结构,每个文件代表一个资源。这些 .tscn 文件包含一个引用 Blender 导出的 glTF 文件的节点,因此任何更改都会被自动获取。它们还允许我们在 .tscn 文件中分配额外的节点和脚本,以便在 Godot 中手动指定每个资源的游戏逻辑。
所有材质都已去重,并引用外部资源 .tres 文件,这些文件会在导入时自动更新。因此,我们 Blender 着色器支持的所有设置都可以在 Blender 中调整并在导入时更新。所有其他仅在 Godot 端生效的设置都在此处控制。
我们与一个由多名艺术家组成的团队合作完成了这个项目。版本控制也是我们管线中至关重要的一部分。Godot 会在导入时生成大量数据。因此,如果一位艺术家提交了导出的 glTF 文件就完事了,那么在其他艺术家的机器上,Godot 会自动导入该文件并生成导入数据。
对于独立开发游戏的单人来说,这不算什么问题,但对我们来说,这确实是一个问题。因此,在提交更改之前,每个人都必须在 Godot 中打开游戏,以便 Godot 有机会创建导入数据,然后将其与新的导出数据一起提交,这一点非常重要。
我们的方法存在一些问题。如果重新开始的话,我会采取不同的做法。
中央资源索引是一个很大的摩擦点,经常导致合并冲突,因为这是一个需要多人不断写入的文件。
在新版本中,我不会将资源索引写入需要版本控制的集中位置,而是根据客户端的资源层次结构动态构建。
另一个问题是,复制资源意味着它们的 ID 也会被复制。我们经常遇到这样的问题:通过复制索引中已经列出的另一个资源,创建的多个材质会发生冲突。到目前为止,解决这个问题的唯一方法是在复制后手动删除 ID。自动化这个过程很棘手,因为我无法连接到复制过程本身,而且之后很难确定哪个是真的,哪个是假的。
如果 Blender 像 Godot 一样引入 UID,这也可以用于更好地在程序之间进行映射。 (纯属假设……)
材质的导出方式,导致我们在游戏文件中没有一个统一的材质设置基准。属性取决于导入的顺序。这通常不是什么大问题,但未来我会将材质的导出数据分离到它们各自的专用 glTF 文件中,就像我们对其他资源所做的那样。
除了我们自己的项目之外,当然还有其他正在进行的努力,旨在实现 Blender 和 Godot 之间流畅的工作流程。其中很大一部分是基于 Khronos Group 领导的 glTF 交换格式的开发,以及该格式在游戏开发中的各种扩展。
例如,其中一项开发是 用于复杂场景的 glTF。这将取代我们构建管线时所依赖的大量功能,从而实现不同 glTF 资源的嵌套。
Godot 基金会的各位好心人一直非常热心地帮助我们,使项目取得成功。即使在项目结束后,我仍然真心希望我们能抽出时间聚在一起,找到一种方法来解决我们在制作过程中遇到的一些小问题。
当然,记录我们的工作固然很好,但实际分享代码又是另一回事。
我想确保大家清楚,这只是我们内部为管线构建的一个原型,我们只是以此为原型进行分享,而不是像我们的 Blender Studio Tools 那样将其作为一个可用的产品进行分享。
要使其成为一个功能齐全、易于使用且足够灵活以集成到管线中的工具,还需要大量额外的工作。目前,我们更愿意将精力投入到确保 Blender 和 Godot 支持原生流畅的开箱即用工作流程上。
目前还没有文档,我们也无法提供支持或使用。
话虽如此,查看代码或许对某些人仍然有用,或者您甚至可以亲自运行它。
以下是完整的生产代码库,包含导出 Blender 扩展和导入 Godot 的流程设置。插件:
Blender 文件 - 9.9 GB - CC-BYdogwalk-repo.zip
加入 并发表评论。