创建实例

备注

本教程涉及在编辑器中实例化场景。要了解如何通过代码实例化场景,请参见 节点与场景实例

下面描述的 Godot 的 实例化 方法不应与硬件实例化混淆,后者可以用来快速渲染大量相似的对象。请参见 使用 MultiMesh 优化

上一部分中,我们了解到场景是一系列组织成树状结构的节点,其中只有一个节点是根节点。你可以将项目拆分成任意数量的场景。这一特性可以帮你将游戏拆解成不同的组件,并进行组织。

你可以创建任意数量的场景并将他们保存成扩展名为 .tscn (“text scene” 文本场景)的文件。上节课的 label.tscn 文件就是一个例子。我们把这些文件叫作“打包的场景”(Packed Scene),因为它们将场景的内容信息进行了打包。

这有一个小球的例子。它由以下内容组成:一个叫“Ball”的 RigidBody2D 节点是根节点,可以让小球下落、在撞墙后反弹;一个 Sprite2D 节点以及一个 CollisionShape2D

../../_images/instancing_ball_scene.webp

保存场景过后,这个场景就可以作为蓝图使用:你可以在其他场景中进行任意次数的重用。像这样从模板中复制对象被称为实例化

../../_images/instancing_ball_instances_example.webp

我们在上一部分提到过,实例化场景的行为与节点类似:编辑器默认会隐藏其中的内容。实例化 Ball 之后,你只会看到 Ball 节点。请注意制作出的副本,名字是唯一的。

Ball 场景的实例最开始都和 ball.tscn 有相同的结构和属性。不过你也可以单独修改各个实例,比如修改反弹的方式、重量等源场景所暴露的属性。

实践

让我们来实践一下实例化,看看到底在 Godot 里是如何使用的。我们为你准备了小球的示例项目,欢迎下载:instancing_starter.zip

先将该压缩包解压到你的计算机里。要导入它,你需要项目管理器。项目管理器可以通过打开 Godot 来访问,或者如果你已经打开了 Godot,点击 Project > Quit to Project ListCtrl + Shift + Q,macOS 为 Ctrl + Option + Cmd + Q

在项目管理器中点击 Import 按钮来导入这个项目。

../../_images/instancing_import_button.webp

在弹出的窗口中,导航至你提取的文件夹。双击 project.godot 文件打开它。

../../_images/instancing_import_project_file.webp

最后点击 导入 按钮。

../../_images/instancing_import_and_edit_button.webp

A window notifying you that the project was last opened in an older Godot version may appear. That's not an issue. Click OK to open the project.

这个项目里包含两个被打包的场景:一个是``main.tscn``场景,其中包含了会与小球发生碰撞的墙体,另一个是``ball.tscn``场景 。而 Main 场景应该会被自动打开。如果你看到的是空的 3D 场景而不是 Main 场景,请单击屏幕顶部的 2D 按钮。

../../_images/instancing_2d_scene_select.webp ../../_images/instancing_main_scene.webp

让我们为 Main 节点添加一个小球作为子节点。在“场景”面板中,选择 Main 节点。然后点击场景面板顶部的链接图标。这个按钮的作用是为当前选中节点添加另一个场景的实例作为子节点。

../../_images/instancing_scene_link_button.webp

双击小球场景来实例化。

../../_images/instancing_instance_child_window.webp

小球会出现在视口的左上角。

../../_images/instancing_ball_instanced.webp

点击它,然后拖拽到视图的中心。

../../_images/instancing_ball_moved.webp

F5 (在macOS上是 Cmd + B )运行游戏。你应该会看到它往下掉。

现在我们希望创建更多的 Ball 节点实例。保持小球仍处于选中的状态,按下 Ctrl + D(macOS 则是 Cmd + D)调用制作副本命令。点击并将新的小球拖到别的位置。

../../_images/instancing_ball_duplicated.webp

你可以重复这个过程在场景中多建几个。

../../_images/instancing_main_scene_with_balls.webp

再次运行游戏。现在你应该看到每个小球都各自下落。这就是实例的作用。每一个都是模板场景的独立副本。

编辑场景和实例

实例还有很多用法。使用这个特性,你可以:

  1. 使用 检查器修改一个小球的属性,这样不会影响到其他的小球。

  2. 打开 ball.tscn 场景修改 Ball 节点,从而修改所有 Ball 的默认属性。在保存时,项目中所有 Ball 的实例都会更新其属性值。

备注

修改实例上的属性总是会覆盖对应打包场景中的值。

让我们来试一试。双击文件系统面板中的 ball.tscn 来打开它。

../../_images/instancing_ball_scene_open.webp

在左侧的场景停靠面板中选择 Ball 节点,然后在右侧的 Inspector 中点击展开 PhysicsMaterial 属性。

../../_images/instancing_physics_material_expand.webp

将其 Bounce(弹力)属性设为 0.5 ,只要点击对应的数字字段、输入 0.5 、然后按 Enter 就可以了。

../../_images/instancing_property_bounce_updated.webp

F5 (在 macOS 中使用 Cmd + B ) 运行游戏,请注意所有的小球都更有弹性了。因为 Ball 场景是所有实例的模板,对它进行修改并保存,就会导致所有实例同时进行更新。

现在让我们来调整单个实例。点击视口上方的对应选项卡回到 Main 场景。

../../_images/instancing_scene_tabs.webp

选择一个 Ball 实例节点,然后 Inspector 中将其 Gravity Scale 设为 10

../../_images/instancing_property_gravity_scale.webp

在被调整过的属性旁边就会多一个灰色的“复原”按钮。

../../_images/instancing_property_revert_icon.webp

这个图标表示你覆盖了源打包场景中的值。即使你修改了原始场景中的这个属性,这个覆盖后的值也还是会保留在这个实例中。点击复原图标会将属性恢复成保存场景中的值。

重新运行游戏,请注意这个小球会比其他小球落得快得多。

备注

您可能会注意到,无法修改球体的 PhysicsMaterial 中的值。这是因为 PhysicsMaterial 是一个 资源,在您把该资源所属场景链接到新场景中的情况下,要在新场景中编辑该资源,就必须先使该资源在新场景中变为独立。要使一个资源在某个出现它的地方变为独立,请在 Inspector 中右键点击 Physics Material 属性,然后在上下文菜单中选择 Make Unique

资源也是 Godot 游戏的关键组件,我们会在后续课程中介绍。

作为设计语言的场景实例

Godot中的实例和场景提供了一种优秀的设计语言,使该引擎与其他引擎不同。我们从一开始就围绕这个概念设计Godot。

我们建议在使用 Godot 制作游戏时忽略架构代码模式,例如模型-视图-控制器 (MVC) 或实体关系图。相反,你可以从想象玩家将在游戏中看到的元素开始,并围绕它们构建代码。

例如,你可以这样拆解一个射击游戏:

../../_images/instancing_diagram_shooter.png

你可以为几乎任何类型的游戏绘制类似的图表。每个矩形代表从玩家视角可见的游戏实体。箭头指向每个场景的实例化者。

在得到这样的图之后,建议你为其中的每一个元素都创建一个场景。你可以通过代码或者直接在编辑器里将其实例化来构建你的场景树。

程序员们乐于花费大量时间来设计抽象的架构,尽力使得组件能够适用于这个架构。基于场景的设计取代了这种方法,使得开发更快、更直接,能够让你去专注于游戏逻辑本身。因为大多数游戏的组件都是直接映射成一个场景,所以使用基于场景实例化的设计意味着需要很少的其他架构代码。

这里是另一个更复杂的开放世界类游戏的示例,这个示例包括有很多资产和嵌套元素:

../../_images/instancing_diagram_open_world.png

想象一下,我们从创建房间开始。我们可以制作几个不同的房间场景,在其中有独特的家具安排。后来,我们可以制作一个房屋场景,在内部使用多个房间实例。我们将用许多实例化的房子和一个大的地形来创建一个城堡,我们将把城堡放在这个地形上。每一个场景都将是一个或多个子场景的实例。

之后,我们可以创建代表守卫的场景,将它们加到城堡之中。也就会间接地加到了游戏世界里。

使用 Godot,就可以很容易地像这样迭代你的游戏,因为你需要做的就是创建并实例化更多的场景。我们将编辑器设计成了易于程序员、设计师、艺术家使用的形式。一个典型的团队开发过程会涉及 2D 或 3D 美术、关卡设计师、游戏设计师、动画师等,他们都可以用 Godot 编辑器工作。

总结

实例化,从蓝图生成对象的过程有许多方便的用途。通过场景,它为你提供:

  • 能将你的游戏分离成可以重复利用的组件。

  • 一个构建和封装复杂系统的工具。

  • 一种以自然方式思考游戏项目结构的语言。