Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

创建实例

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

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

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

../../_images/instancing_ball_scene.png

保存场景过后,这个场景就可以作为蓝图使用:你可以在其他场景中进行任意数量的翻制。将对象根据模板进行翻制的这一过程就叫作实例化

../../_images/instancing_ball_instances_example.png

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

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

实践

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

将存档解压到你的计算机里。你需要项目管理器来导入它。通过打开 Godot 来访问项目管理器,或者如果你已经打开了 Godot,请单击 项目 -> 推出到项目列表 (Ctrl + Shift + Q, Ctrl + Option + Cmd + macOS 上的 Q

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

../../_images/instancing_import_button.png

在弹出框中点击浏览按钮,定位到刚才解压的文件夹。

../../_images/instancing_import_browse.png

双击打开 project.godot 文件。

../../_images/instancing_import_project_file.png

最后点击“导入并编辑”按钮。

../../_images/instancing_import_and_edit_button.png

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

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

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

../../_images/instancing_scene_link_button.png

双击小球场景来实例化。

../../_images/instancing_instance_child_window.png

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

../../_images/instancing_ball_instanced.png

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

../../_images/instancing_ball_moved.png

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

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

../../_images/instancing_ball_duplicated.png

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

../../_images/instancing_main_scene_with_balls.png

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

编辑场景和实例

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

  1. 使用“检查器”修改一个小球的属性,不影响其他实例。

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

备注

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

让我们来试一试。打开 ball.tscn 然后选中 Ball 节点。在右侧的“检查器”中,点击展开 PhysicsMaterial 属性。

../../_images/instancing_physics_material_expand.webp

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

../../_images/instancing_property_bounce_updated.webp

Play the game by pressing F5 (Cmd + B on macOS) and notice how all balls now bounce a lot more. As the Ball scene is a template for all instances, modifying it and saving causes all instances to update accordingly.

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

../../_images/instancing_scene_tabs.png

选择一个 Ball 实例节点,然后“检查器”中将 Gravity Scale(重力缩放)设为 10

../../_images/instancing_property_gravity_scale.png

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

../../_images/instancing_property_revert_icon.png

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

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

备注

You may notice you are unable to change the values of the PhysicsMaterial of the ball. This is because PhysicsMaterial is a resource, and needs to be made unique before you can edit it in a scene that is linking to its original scene. To make a resource unique for one instance, right-click on it in the Inspector and click Make Unique in the contextual menu.

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

作为设计语言的场景实例

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

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

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

../../_images/instancing_diagram_shooter.png

对于几乎任何类型的游戏,都可以想出这样的图表。矩形表示的是从玩家角度可以在游戏中看到的实体,箭头表示的是场景之间的从属关系。

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

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

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

../../_images/instancing_diagram_open_world.png

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

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

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

总结

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

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

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

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