创建实例

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

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

Here's the example of a ball. It's composed of a RigidBody2D node as its root named Ball, which allows the ball to fall and bounce on walls, a Sprite node, and a CollisionShape2D.

../../_images/instancing_ball_scene.png

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

../../_images/instancing_ball_instances_example.png

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

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

实践

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

将压缩包解压到电脑上。然后打开 Godot,在项目管理器中点击“导入”按钮来导入这个项目。

../../_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 场景。

../../_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 运行游戏。你应该会看到它往下掉。

现在我们希望创建更多的 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.png

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

../../_images/instancing_property_bounce_updated.png

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

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

../../_images/instancing_scene_tabs.png

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

../../_images/instancing_property_gravity_scale.png

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

../../_images/instancing_property_revert_icon.png

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

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

注解

如果你修改了一个实例中的 PhysicsMaterial,那么就会影响到其他所有实例。这是因为 PhysicsMaterial 是一个资源,而资源是跨实例共享的。要让某个实例的资源唯一,请在“检查器”中对其右键,然后选择弹出菜单中的“唯一化”。

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

作为设计语言的场景实例

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

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

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

../../_images/instancing_diagram_shooter.png

You can come up with a diagram like this for almost any type of game. Each rectangle represents an entity that's visible in the game from the player's perspective. The arrows tell you which scene owns which.

Once you have a diagram, we recommended creating a scene for each element listed in it to develop your game. You'll use instancing, either by code or directly in the editor, to build your tree of scenes.

Programmers tend to spend a lot of time designing abstract architectures and trying to fit components into it. Designing based on scenes makes development faster and more straightforward, allowing you to focus on the game logic itself. Because most game components map directly to a scene, using a design based on scene instantiation means you need little other architectural code.

Here's the example of a scene diagram for an open-world game with tons of assets and nested elements:

../../_images/instancing_diagram_open_world.png

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

Later, we could create scenes representing guards and add them to the citadel. They would be indirectly added to the overall game world.

With Godot, it's easy to iterate on your game like this, as all you need to do is create and instantiate more scenes. We designed the editor to be accessible to programmers, designers, and artists alike. A typical team development process can involve 2D or 3D artists, level designers, game designers, and animators, all working with the Godot editor.

总结

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

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

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

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