导入 3D 场景

Godot 场景导入器

在处理 3D 素材时,Godot 有一个非常灵活且可配置的导入器。

Godot 使用的是场景。这意味着用你最喜爱的 3D 软件制作的整个场景可以尽可能完整地被导入。

Godot 支持以下 3D 场景文件格式

  • glTF 2.0 (推荐使用)。Godot 完全支持文本(.gltf)和二进制( .glb )格式。

  • DAE(COLLADA):一个比较老的格式,当然完全支持。

  • OBJ(Wavefront)格式 + 他们的 MTL 材质文件。这也是完全支持的,但相当有限(不支持轴心、骨架、动画、PBR 材质……)。

  • ESCN,是 Godot 特有的格式,Blender 可以用插件导出。

  • FBX,通过 Open Asset Import library 提供支持。然而,FBX 是专属格式,所以如果无特殊要求的话,推荐使用上面列出的格式。

只需将场景文件和纹理一起复制到项目仓库中,Godot 就可以完全导入。

在输出时,网格不会被骨骼变形很重要。在使用您喜欢的 3D 编辑器进行导出之前,请确保将骨架重置为其 T 姿势或默认的放松姿势。

从 Maya 和 3DS Max 导出的 DAE 文件

Autodesk 为 Maya 和 3DS Max添加了内置的 COLLADA 支持, 但默认情况下已损坏, 因此不应使用. 导出此格式的最佳方法是使用 OpenCollada 插件. 尽管它们并非总是与最新版本的软件保持一致, 但它们可以很好地工作.

从 Blender 导出 glTF 2.0 文件

从 Blender 导出 glTF 文件的方法有三种。可以导出为二进制 glTF(.glb 文件)、嵌入式 glTF(.gltf 文件)、以及附带纹理形式(gltf + .bin + 纹理)。

二进制 glTF 文件是三个选项中最小的。包含在 Blender 中设置的网格和纹理。当放入 Godot 中时,纹理将成为对象材质文件的一部分。

嵌入式 glTF 文件的功能与二进制文件相同。没有在 Godot 中提供额外的功能,也不应使用,因为它们的文件较大。

将 glTF 与纹理分开使用的原因有两个。一是将场景以基于文本的格式和二进制数据,描述在单独的二进制文件中。这对于版本控制很有用,如果要基于文本格式评审更改。二是您需要将纹理文件与材质文件分开。如果您不需要这些 glTF 二进制文件的任一个,也可以。

警告

Blend shape animations cannot be imported - they require manual animation within Godot.

备注

Blender versions older than 3.2 do not export emissive textures with the glTF file. If your model uses one and you’re using an older version of Blender, it must be brought in separately.

默认情况下,Blender 在材质上禁用背面剔除,导出材质时匹配其在 Blender 中的渲染方式。这意味着 Godot 中的材质会将其剔除模式设置为 Disabled。这会降低性能,因为背面将被渲染,即使它们不可见。要解决此问题,请在 Blender 的材质选项卡中启用 Backface Culling ,然后再次将场景导出为 glTF。

从 Blender 导出的 DAE 文件

Blender 也有内置的 COLLADA 支持,但不能满足游戏引擎的需求,不能完全正常工作,不应该使用。

Godot 提供了一个 Blender 插件,可以正确导出 COLLADA 场景供 Godot 使用。它不能在 Blender 2.8 或更新的版本中使用,但有计划在未来更新它。

从 Blender 导出 ESCN 文件

最强大的一个, 叫做 godot-blender-exporter . 它使用的是.escn文件, 这也是.tscn文件(Godot场景文件)的另一种名称;它从Blender场景中保留了尽可能多的信息. 然而, 它被认为是试验性的.

ESCN 导出器有一个详细的` 文档 <escn_exporter/index.html>`__,描述了它的功能和用法。

单独导出纹理

虽然纹理可以和模型一起以某些文件格式导出, 如glTF 2.0, 但您也可以单独导出它们.Godot的材质使用PBR(基于物理的渲染), 所以如果一个纹理程序可以导出PBR纹理, 它们就可以在Godot中工作. 这包括 Substance suite , ArmorPaint (开源) , Material Maker (开源) .

备注

关于 Godot 材质的更多信息,请参阅 空间材质

导出注意事项

由于 GPU 只能渲染三角形,所以包含四边形或 N 边形的网格必须在渲染前进行三角剖分。Godot 可以在导入时对网格进行三角剖分,但结果可能无法预测或不正确,特别是对于 N 边形。无论目标应用是什么,在导出场景之前进行三角剖分会得到更一致的结果,因此应该尽可能地进行三角剖分。

为了避免在Godot中导入后出现三角剖分不正确的问题, 建议让3D DCC自行对对象进行三角剖分. 在Blender中, 可以通过向对象添加三角剖分修改器, 并确保在导出对话框中勾选 应用修改器 来实现. 另外, 根据导出工具的不同, 您可以在导出对话框中找到并启用 Triangulate Faces 选项.

为了避免在编辑器中出现3D选择的问题, 建议在导出场景前在3D DCC中应用对象变换.

导入工作流程

Godot场景导入器允许有关如何导入数据的不同工作流. 根据许多选项, 可以通过以下方式导入场景:

  • 外部材质(默认): 将每种材质保存到文件资源的位置. 保留对它们的修改.

  • 外部网格: 每个网格被保存到不同文件的位置. 许多用户喜欢直接处理网格.

  • 外部动画: 允许在源更改时, 修改和合并保存的动画.

  • 外部场景: 将每个导入场景的根节点保存为单独的场景.

  • 单场景: 内置所有内容的单场景文件.

../../_images/scene_import1.png

由于不同的开发人员有不同的需求, 因此此导入过程是高度可定制的.

导入选项

导入器有几种选项, 这将在下面讨论:

../../_images/scene_import2.png

节点

根类型

默认情况下,导入场景中根节点的类型为“Spatial”,但是可以对其进行修改。

根名称

允许为生成的根节点设置特定名称.

根规模

根节点的规模.

自定义脚本

可以提供一个特殊脚本, 来处理导入后的整个场景. 这非常适合后期处理, 更换材质, 对几何图形做有趣的事情等.

创建如下的脚本:

  1. tool # Needed so it runs in the editor.
  2. extends EditorScenePostImport
  3. func post_import(scene):
  4. # Do your stuff here.
  5. return scene # remember to return the imported scene

post_import 函数将导入的场景作为参数(参数实际上是场景的根节点). 必须返回最终将要使用的场景. 它可以是不同的.

存储

默认情况下,Godot导入一个单独的场景. 此选项允许指定根下面的节点将是一个单独的场景, 并被实例化到导入的场景中.

当然, 在其他地方手动实例导入的场景也是可以的.

材质

位置

Godot 支持网格或节点中的材质. 默认情况下, 材质将放置在每个节点上.

存储

材质可以存储在场景中或外部文件中. 默认情况下, 它们存储在外部文件中, 因此可以进行编辑. 这是因为大多数 3D 数字创作软件没有与 Godot 中的相同的材质选项.

当材质是内置的时, 每当源场景被修改并重新导入时, 它们都会丢失.

备注

除非你在重新导入之前删除相关的 .material 文件, 否则Godot不会重新导入存储在外部文件中的素材.

如要在每次重新导入 3D 场景时强制重新导入材质, 请在文件系统面板中选中 3D 场景中的材质存储模式, 然后进入导入面板, 将 材质 > 存储 设置为 内置 而不是 文件 .

保持开启重新导入

一旦将材质编辑为使用Godot功能, 导入器将保留已编辑的材质, 并忽略来自源场景的材料. 仅当材质保存为文件时, 此选项才存在.

网格

压缩

使网格对网格的多个方面使用不太精确的数字以节省空间.

这些是:

  • 变换矩阵(位置, 旋转, 和缩放):32位浮点数到16位有符号整数.

  • 顶点:32 位浮点数到16位有符号整数.

  • 法线:32 位浮点数到32位无符号整数.

  • 切线:32 位浮点数到32位无符号整数.

  • 顶点色:32 位浮点数到32位无符号整数.

  • UV:32 位浮点数到32位无符号整数.

  • UV2:32 位浮点数到32位无符号整数.

  • 顶点权重:32 位浮点数到32位无符号整数.

  • 骨架骨骼:32 位浮点数到16位无符号整数.

  • 数组索引: 基于具体有多少元素,32位或16位无符号整数.

附加信息:

  • UV2 = 用于细节纹理和烘焙光照纹理的第二个 UV 通道.

  • 数组索引 = 一个数字数组, 它为上面数组的每个元素计数;即, 它们的顶点和法线的数量.

在某些情况下, 这可能会导致精度损失, 因此可能需要禁用此选项. 例如, 如果网格非常大或导入了多个网格覆盖巨大的区域, 则压缩此网格的导入, 可能会导致几何图形的间隙, 或顶点不在它们应在的位置.

确保切线

如果要使用法线贴图的纹理,网格需要有切线数组。这个选项可确保如果这些数组在源场景中不存在,就会生成它们。Godot 使用 Mikktspace 来进行生成,但最好让它们在导出器中生成。

存储

网格可以存储在单独的文件(资源)中, 而不是内置的. 除非有人想直接用它们建立对象, 否则这没有多少实际用途.

提供此选项是为了帮助那些喜欢直接使用网格而不是场景的人.

光线烘焙

网格是否用于烘焙光照贴图中.

  • 禁用: 网格未用于烘焙的光照贴图中.

  • 启用: 网格用于烘焙的光照贴图中.

  • Gen光照贴图: 网格用于烘焙光照贴图中, 并为光照贴图展开第二个UV层.

备注

有关光线烘焙的更多信息, 请参阅 烘焙光照贴图.

外部文件

生成的网格和材质可以选择存储在具有场景名称的子目录中.

动画选项

Godot提供了许多有关如何处理动画数据的选项. 一些导出器(如Blender)可以在一个文件中生成许多动画. 其他的, 如3DS Max 或 Maya, 需要将许多动画放入同一时间线, 或者最糟糕的情况是将每个动画放在单独的文件中.

../../_images/scene_import3.png

默认情况下启用动画导入.

注意

要修改导入的 3D 场景中的动画, 您需要在导入栏中将动画存储选项从 内置 改为 文件 . 否则, 在项目运行时, 对Godot中的动画所做的修改将丢失.

FPS

大多数3D导出格式都以秒而不是帧的形式存储动画时间轴. 为确保尽可能真实地导入动画, 请指定用于编辑动画的每秒帧数. 未能这么做, 可能会导致动画不稳定.

过滤器脚本

可以使用特殊语法指定过滤器脚本, 以决定应保留哪些动画的哪些轨道.

过滤器脚本会针对每个导入的动画执行. 语法由两种类型的语句组成, 一种用于选择要过滤的动画, 另一种用于过滤匹配的动画中的各个轨道. 所有名称模式均使用不区分大小写的表达式匹配, 可以使用通配符 ?* (内部使用 String.matchn() ).

脚本必须以动画过滤器语句开头(如以 @ 开头的行表示)。例如,如果我们想要将过滤器应用在所有以 "_Loop" 结尾的导入动画上:

  1. @+*_Loop

类似地,还可以在同一行中添加其他模式,以逗号分隔。下面是一个修改后的例子,它额外包含所有名称以 "Arm_Left" 开头的动画,同时排除所有名称以 "Attack" 结尾的动画:

  1. @+*_Loop, +Arm_Left*, -*Attack

在动画选择过滤器语句之后, 我们添加轨道过滤模式来指示保留或丢弃哪些动画轨道. 如果未指定轨道过滤器模式, 则匹配动画中的所有轨道都会被丢弃!

需要注意的是, 轨道过滤器表达式是按顺序作用于动画中的每条轨道, 这意味着, 一行表达式可能包含某个轨道, 但后续的规则仍然可以忽略它. 同样, 一个被之前规则排除的轨道, 可能被过滤器脚本后续的规则重新包含进来.

例如:包含动画中所有名字以 "_Loop" 结尾的轨道,但忽略任何以 "Control" 结尾的 "Skeleton" 轨道,除非它们的名字中有 "Arm"

  1. @+*_Loop
  2. +*
  3. -Skeleton:*Control
  4. +*Arm*

在上面的示例中,像 "Skeleton:Leg_Control" 这样的轨道会被丢弃,而像 "Skeleton:Head""Skeleton:Arm_Left_Control" 这样的轨道会被保留。

任何不是以 +- 开头的轨道过滤器行将会被忽略.

存储

默认情况下, 动画保存为内置. 可以将它们保存到一个文件中. 这允许向动画添加自定义轨道并在重新导入后保留它们.

优化

导入动画时, 会运行优化程序, 从而大大减少动画的大小. 一般情况下, 除非您怀疑动画可能因启用而被破坏, 否则应始终启用此功能.

剪辑

可以指定单个时间轴中的多个动画作为剪辑. 这样做的话, 模型必须只有一个命名为 default 的动画. 为了创建剪辑, 把剪辑数量改成比0大的数. 然后可以修改剪辑名字, 指定开始和结束帧, 选择动画是否循环.

场景继承

在许多情况下, 可能需要对导入的场景进行修改. 默认情况下, 这是不可能的, 因为如果源素材发生更改(从3D建模应用程序重新导出了源 .dae, .gltf, .obj),Godot将重新导入 整个场景.

但是, 可以使用 场景继承 进行本地修改. 尝试打开导入的场景, 将出现以下对话框:

../../_images/scene_import4.png

在继承场景中, 修改的唯一限制是:

  • 无法删除节点(但可以在任何位置添加)。

  • 子资源无法被编辑(如上所述它们将保存在外部)

除此之外,一切都是允许的!

导入提示

很多时候,编辑场景时,导出后需要完成一些常见任务:

  • 向对象添加碰撞检测。

  • 将对象设置为导航网格。

  • 删除游戏引擎中未使用的节点(例如用于建模的特定光源)。

为简化此工作流程,Godot 提供了一些后缀,可以将其添加到 3D 建模软件中的对象名称中。导入后,Godot 将检测到它们并自动执行操作。

备注

下面描述的所有后缀都是大小写敏感的。

删除节点(-noimp)

无论是什么类型的节点,具有 -noimp 后缀的对象都会在导入时被移除,不会出现在导入后的场景中。

创建碰撞体(-col、-convcol、-colonly、-convcolonly)

-col 选项只作用于网格物体. 如果该选项被检测到, 将会添加一个静态碰撞体的子节点, 用的是跟网格一样的几何体. 这会创建一个三角形网格碰撞体, 这个选项对碰撞检测来说很慢但是精确. 这个选项通常是关卡几何体需要的(但是也看看下面的 -colonly ).

-convcol 选项将创建一个 ConvexPolygonShape 而不是 ConcavePolygonShape。不像可以是凹型的三角形网格, 一个凸型的形状只能精确的表示它没有任何凹型角度(金字塔是凸型, 但空盒子是凹型). 因此, 凸型碰撞体通常不适用于关卡几何体. 当说到一个很简单的网格时, 凸型碰撞体相对三角形碰撞体有更好的性能. 这个选项适用于简单的物体, 或是需要大多数时精确碰撞检测的动态物体.

然而,在这两个例子中,视觉几何体处理过于复杂或对于碰撞而言不够光滑。物理引擎会出现小故障从而不必要地降低了引擎的速度。

为了解决这个问题, 存在 -colony 修饰符, 该修饰符将在导入时删除网格, 并创建一个 StaticBody 静态碰撞体. 这有助于将可视网格和实际碰撞体分开.

-convcolonly 选项的工作方式类似,但创建的是 ConvexPolygonShape

选项 -colonly 也可以与Blender的空对象一起使用. 导入时, 它将创建一个带有碰撞节点的 StaticBody 作为子节点. 碰撞节点将具有许多预定义的形状之一, 具体取决于Blender的空绘制类型:

../../_images/3dimp_BlenderEmptyDrawTypes.png

可能的话,请试着使用少量图元碰撞形状,而不是三角形网格或凸型体。图元形状的性能和可靠性通常更好。

备注

为了Blender编辑器中更佳的可见性, 可以在碰撞空物体上设置 “透视” 选项, 并在Blender的 用户偏好设置> 主题> 3D视图> 空物体 中为它们设置不同的颜色.

参见

碰撞体全面概述请查看 碰撞形状(3D).

创建导航(-navmesh)

具有 -navmesh 后缀的网格节点, 将被转换为导航网格. 原始网格节点将在导入时被删除.

创建 VehicleBody(-vehicle)

具有 -vehicle 后缀的网格节点, 将作为一个 VehicleBody 节点的子节点被导入.

创建 VehicleWheel(-wheel)

具有 -wheel 后缀的网格节点, 将作为一个 VehicleWheel 节点的子节点被导入.

刚体(-rigid)

具有 -rigid 后缀的网格节点, 将作为一个 RigidBody 节点的子节点被导入.

动画循环(-loop、-cycle)

COLLADA文档中以令牌 loopcycle 开头或结尾的动画剪辑将作为设置了循环标志的Godot动画导入. 这是区分大小写的, 不需要连字符.

在Blender中, 这需要使用NLA编辑器, 并用 loopcycle 前缀或后缀命名该动作.