Godot引擎 4.0 文档 - 手册 - 2D

本文为Google Translate英译中结果,DrGraph在此基础上加了一些校正。英文原版页面:

2D — Godot Engine (stable) documentation in English

画布层

视口和画布项目

CanvasItem是所有 2D 节点的基础,无论是常规的 2D 节点,例如Node2D还是Control。两者都继承自CanvasItem。您可以在树中排列画布项目。每个项目都将继承其父项的变换:当父项移动时,其子项也会移动。

CanvasItem 节点和从它们继承的节点是 显示它们的Viewport的直接或间接子级。

视口的属性 Viewport.canvas_transform允许将自定义Transform2D 转换应用于它包含的 CanvasItem 层次结构。Camera2D等节点 通过更改该变换来工作。

要实现滚动等效果,操作画布变换属性比移动根画布项和整个场景更有效。

但通常情况下,我们不希望游戏或应用程序中的所有内容都受制于画布变换。例如:

  • 视差背景:移动速度比舞台其余部分慢的背景。

  • UI:想象一下叠加在我们游戏世界视图上的用户界面 (UI) 或平视显示器 (HUD)。我们希望生命计数器、分数显示和其他元素即使在我们对游戏世界的看法发生变化时也能保持其屏幕位置。

  • 过渡:我们可能希望用于过渡(淡入淡出、混合)的视觉效果保持在固定的屏幕位置。

如何在单个场景树中解决这些问题?

画布图层

答案是CanvasLayer,这是一个为其所有子级和孙级添加单独的 2D 渲染层的节点。默认情况下,视口子项将在“0”层绘制,而 CanvasLayer 将在任何数字层绘制。编号较大的图层将绘制在编号较小的图层之上。CanvasLayers 也有自己的变换,不依赖于其他图层的变换。这允许 UI 固定在屏幕空间中,而我们对游戏世界的看法发生变化。

这方面的一个例子是创建视差背景。这可以通过“-1”层的 CanvasLayer 来完成。带有分数、生命计数器和暂停按钮的屏幕也可以在“1”层创建。

这是它的外观图:

CanvasLayers 独立于树的顺序,它们只依赖于它们的层号,因此可以在需要时实例化它们。

笔记

CanvasLayers 不需要控制节点的绘制顺序。确保节点正确绘制在“前面”或“后面”的标准方法是操纵场景面板中节点的顺序。也许违反直觉,场景面板中最上面的节点绘制在视口中较低节点的后面。2D 节点还具有 用于控制其绘制顺序的CanvasItem.z_index属性。

视口和画布变换

介绍

这是对节点从本地绘制内容到绘制到屏幕上进行的 2D 变换的概述。本概述讨论了引擎的非常底层的细节。

画布变换

正如在之前的教程Canvas layers中提到的,每个 CanvasItem 节点(请记住,基于 Node2D 和 Control 的节点使用 CanvasItem 作为它们的公共根)都将驻留在Canvas Layer中。每个画布层都有一个可以作为Transform2D访问的变换(平移、旋转、缩放等) 。

在上一教程中也介绍过,节点默认绘制在内置画布的第 0 层中。要将节点放在不同的层中,可以使用CanvasLayer节点。

全局画布变换

视口也有一个 Global Canvas 变换(也是一个 Transform2D)。这是主变换并影响所有单独的画布层变换。一般这个transform用处不大,只是在Godot的编辑器中的CanvasItem Editor中用到了。

拉伸变换

最后,视口有一个Stretch Transform,在调整屏幕大小或拉伸屏幕时使用。此变换在内部使用(如多分辨率中所述),但也可以在每个视口上手动设置。

输入事件乘以这个转换但缺少上面的那些。为了将 InputEvent 坐标转换为本地 CanvasItem 坐标, 为方便起见,添加了CanvasItem.make_input_local()函数。

变换顺序

要使 CanvasItem 局部属性中的坐标成为实际屏幕坐标,必须应用以下转换链:

变换函数

获取每个变换可以通过以下函数实现:

类型

转换

画布项目

CanvasItem.get_global_transform()

画布图层

CanvasItem.get_canvas_transform()

CanvasLayer+GlobalCanvas+Stretch

CanvasItem.get_viewport_transform()

最后,然后,要将一个 CanvasItem 本地坐标转换为屏幕坐标,只需按以下顺序相乘:

GD脚本C#
var screen_coord = get_viewport_transform() * (get_global_transform() * local_pos)

但是请记住,通常不希望使用屏幕坐标。推荐的方法是简单地在 Canvas 坐标 ( ) 中工作CanvasItem.get_global_transform(),以允许自动屏幕分辨率调整正常工作。

提供自定义输入事件

通常需要将自定义输入事件提供给场景树。有了以上知识,要正确地做到这一点,必须按照以下方式进行:

GD脚本C#
var local_pos = Vector2(10, 20) # local to Control/Node2D
var ie = InputEventMouseButton.new()
ie.button_index = MOUSE_BUTTON_LEFT
ie.position = get_viewport_transform() * (get_global_transform() * local_pos)
get_tree().input_event(ie)

二维灯光和阴影

介绍

默认情况下,Godot 中的 2D 场景是无阴影的,没有可见的灯光和阴影。虽然渲染速度很快,但未着色的场景可能看起来很平淡。Godot 提供了使用实时 2D 光照和阴影的能力,这可以极大地增强项目的深度感。

没有 2D 灯光或阴影,场景没有阴影

启用 2D 灯(无阴影)

启用 2D 灯光和阴影

节点

完整的 2D 照明设置涉及多个节点:

CanvasModulate用于通过指定将充当基本“环境”颜色的颜色来使场景变暗。这是任何 2D 光都无法到达的区域的最终照明颜色。如果没有 CanvasModulate 节点,最终场景看起来会太亮,因为 2D 灯光只会照亮现有的未着色外观(看起来完全亮起)。

Sprite2D用于显示光斑、背景和阴影投射器的纹理。

PointLight2D用于照亮场景。灯光通常的工作方式是通过在场景的其余部分添加选定的纹理来模拟照明。

LightOccluder2D用于告诉着色器场景的哪些部分投射阴影。这些遮挡物可以作为独立节点放置,也可以作为 TileMap 节点的一部分。

阴影仅出现在 PointLight2D 覆盖的区域并且它们的方向基于 Light的中心。

笔记

背景颜色不接收任何光照。如果你想让光线投射到背景上,你需要为背景添加一个视觉表示,比如 Sprite2D。

Sprite2D 的区域属性有助于快速创建重复背景纹理,但请记住还要在 Sprite2D 的属性中将Texture > Repeat设置为 Enabled 。

点光源

点光源(也称为位置光源)是二维照明中最常见的元素。点光源可用于表示来自火炬、火、射弹等的光。

PointLight2D 提供以下属性以在检查器中进行调整:

  • 纹理:用作光源的纹理。纹理的大小决定了光的大小。纹理可能有一个 alpha 通道,这在使用 Light2D 的Mix混合模式时很有用,但如果使用Add(默认)或Subtract混合模式则不需要。

  • 偏移量:光纹理的偏移量。与移动灯光节点不同,更改偏移不会导致阴影移动。

  • Texture Scale:灯光大小的乘数。较高的值将使光线延伸得更远。较大的灯具有较高的性能成本,因为它们会影响屏幕上的更多像素,因此在增加灯的尺寸之前请考虑这一点。

  • 高度:灯光相对于法线贴图的虚拟高度。默认情况下,光线非常靠近接收光线的表面。如果使用法线贴图,这将使光照几乎不可见,因此请考虑增加该值。调整灯光的高度只会在使用法线贴图的表面上产生明显的差异。

如果您没有要在灯光中使用的预制纹理,您可以使用这个“中性”点光源纹理(右键单击 > 将图像另存为...):

中性点光质感

如果您需要不同的衰减,您可以通过在灯光的Texture属性上分配一个New GradientTexture2D来按程序创建纹理。创建资源后,展开其Fill部分并将填充模式设置为Radial。然后你必须调整渐变本身,从不透明的白色开始到透明的白色,并将它的起始位置移动到中心。

定向光

Godot 4.0 中的新功能是能够在 2D 中进行定向照明。定向照明用于表示阳光或月光。光线彼此平行投射,就好像太阳或月亮距离接收光线的表面无限远。

DirectionalLight2D 提供以下属性:

  • 高度:关于法线贴图的光的虚拟高度(0.0 = 平行于表面,1.0= 垂直于表面)。默认情况下,光线与接收光线的表面完全平行。如果使用法线贴图,这将使光照几乎不可见,因此请考虑增加该值。调整灯光的高度只会在使用法线贴图的表面上产生视觉差异。高度不影响阴影的外观。

  • Max Distance:在剔除阴影之前,物体与摄像机中心物体的最大距离(以像素为单位)。减小此值可以防止位于相机外部的对象投射阴影(同时还可以提高性能)。Max Distance未考虑 Camera2D 缩放,这意味着在缩放值较高时,在缩放到给定点时阴影似乎会更快淡出。

笔记

无论Height属性的值如何,定向阴影总是看起来无限长。这是 Godot 中用于 2D 灯的阴影渲染方法的限制。

要获得不是无限长的定向阴影,您应该在 DirectionalLight2D 中禁用阴影并改用从 2D 有符号距离字段读取的自定义着色器。这个距离场是从场景中存在的 LightOccluder2D 节点自动生成的。

常见的灯光属性

PointLight2D 和 DirectionalLight2D 都提供公共属性,它们是 Light2D 基类的一部分:

  • 已启用:允许切换灯光的可见性。与隐藏灯光节点不同,禁用此属性不会隐藏灯光的子节点。

  • Editor Only:如果启用,灯光仅在编辑器内可见。它将在正在运行的项目中自动禁用。

  • 颜色:灯光的颜色。

  • 能量:光的强度倍增器。较高的值会产生更亮的光。

  • 混合模式:用于光计算的混合公式。默认 添加适用于大多数用例。减法可用于负光,物理上不准确但可用于特殊效果。Mix混合模式通过线性插值将光纹理对应的像素值与其下方的像素值混合

  • Range > Z Min:受光影响的最低 Z 指数。

  • Range > Z Max:受光影响的最高 Z 指数。

  • Range > Layer Min:受光影响的最低视觉层。

  • Range > Layer Max:受光影响的最高视觉层。

  • Range > Item Cull Mask:控制哪些节点从该节点接收光,具体取决于其他节点启用的可视层Occluder Light Mask。这可用于防止某些物体接收光。

设置阴影

在 PointLight2D 或 DirectionalLight2D 节点上启用Shadow > Enabled属性后,最初您不会看到任何视觉差异。这是因为场景中的节点还没有任何遮挡物,遮挡物用作阴影投射的基础。

要在场景中出现阴影,必须将 LightOccluder2D 节点添加到场景中。这些节点还必须具有旨在匹配精灵轮廓的遮挡多边形。

连同它们的多边形资源(必须设置为具有任何视觉效果),LightOccluder2D 节点具有 2 个属性:

  • SDF Collision:如果启用,遮挡物将成为实时生成的有符号距离场的一部分,可用于自定义着色器。当不使用从这个 SDF 读取的自定义着色器时,启用它不会产生视觉差异并且没有性能成本,因此为了方便起见默认情况下启用它。

  • Occluder Light Mask:这与 PointLight2D 和 DirectionalLight2D 的Shadow > Item Cull Mask属性一起使用,以控制哪些对象为每个光投射阴影。这可用于防止特定对象投射阴影。

有两种创建遮光器的方法:

自动生成遮光器

通过选择节点,单击2D 编辑器顶部的 Sprite2D菜单,然后选择Create LightOccluder2D Sibling ,可以从 Sprite2D 节点自动创建遮挡物。

在出现的对话框中,轮廓将围绕您的精灵的边缘。如果轮廓与精灵的边缘紧密匹配,您可以单击“确定”。如果轮廓离精灵的边缘太远(或者“侵蚀”到精灵的边缘),请调整Grow (pixels)Shrink (pixels),然后单击Update Preview。重复此操作,直到获得满意的结果。

手动绘制遮光器

创建一个 LightOccluder2D 节点,然后选择该节点并单击 2D 编辑器顶部的“+”按钮。当要求创建多边形资源时,回答 Yes。然后您可以通过单击创建新点开始绘制遮挡多边形。您可以通过右键单击现有点来删除它们,也可以通过单击该线然后拖动来从现有线创建新点。

可以在启用了阴影的 2D 灯光上调整以下属性:

  • 颜色:阴影区域的颜色。默认情况下,阴影区域是全黑的,但可以出于艺术目的进行更改。颜色的 alpha 通道控制阴影被指定颜色着色的程度。

  • Filter:用于阴影的过滤模式。默认的None渲染速度最快,非常适合具有像素艺术美感的游戏(由于其“块状”视觉效果)。如果您想要柔和的阴影,请改用PCF5 。PCF13更柔和,但对渲染的要求最高。由于渲染成本高,PCF13 一次只能用于几个灯。

  • Filter Smooth:控制当Filter设置为PCF5PCF13时应用于阴影的柔化程度 。较高的值会产生较柔和的阴影,但可能会导致条带伪影可见(尤其是使用 PCF5 时)。

  • Item Cull Mask:控制哪些 LightOccluder2D 节点投射阴影,具体取决于它们各自的Occluder Light Mask属性。

硬阴影

软阴影(PCF13,过滤平滑 1.5)

由于 Filter Smooth 太高(PCF5、Filter Smooth 4)导致的带有条纹伪影的柔和阴影

遮挡物绘制顺序

LightOccluder2Ds 遵循通常的 2D 绘图顺序。这对于 2D 光照很重要,因为这是您控制遮挡物是否应该遮挡精灵本身的方式。

如果 LightOccluder2D 节点是sprite 的同级节点,则遮挡器将在场景树中放置在sprite下方时遮挡 sprite 本身。

如果 LightOccluder2D 节点是精灵的子节点,如果在 LightOccluder2D 节点上禁用了Show Behind Parent (这是默认设置) ,则遮挡器将遮挡精灵本身。

法线贴图和高光贴图

法线贴图和高光贴图可以极大地增强 2D 光照的深度感。类似于这些在 3D 渲染中的工作方式,法线贴图可以根据表面接收光的方向(基于每个像素)改变其强度,从而帮助使照明看起来不那么平坦。高光贴图通过使一些光线反射回观察者来进一步帮助改善视觉效果。

PointLight2D 和 DirectionalLight2D 都支持法线贴图和高光贴图。从 Godot 4.0 开始,法线贴图和高光贴图可以分配给任何 2D 元素,包括从 Node2D 或 Control 继承的节点。

法线贴图表示每个像素“指向”的方向。然后引擎使用此信息以物理上合理的方式将光照正确应用到 2D 表面。法线贴图通常是从手绘高度贴图创建的,但它们也可以从其他纹理自动生成。

高光贴图定义每个像素应该反射多少光(如果高光贴图包含颜色,则以哪种颜色反射)。更亮的值将在纹理上的给定点处产生更亮的反射。高光贴图通常是通过手动编辑创建的,使用漫反射纹理作为基础。

提示

如果您的精灵没有法线贴图或高光贴图,您可以使用免费的开源Laigter 工具生成它们。

要在 2D 节点上设置法线贴图和/或高光贴图,请为绘制节点纹理的属性创建一个新的 CanvasTexture 资源。例如,在 Sprite2D 上:

为 Sprite2D 节点创建 CanvasTexture 资源

展开新创建的资源。您可以找到几个需要调整的属性:

  • 漫反射 > 纹理:基色纹理。在此属性中,加载您用于精灵本身的纹理。

  • Normal Map > Texture:法线贴图纹理。在此属性中,加载您从高度贴图生成的法线贴图纹理(请参阅上面的提示)。

  • Specular > Texture:高光贴图纹理,控制漫反射纹理上每个像素的高光强度。高光贴图通常是灰度的,但它也可以包含颜色以相应地增加反射的颜色。在此属性中,加载您创建的镜面贴图纹理(请参阅上面的提示)。

  • Specular > Color:镜面反射的颜色倍增器。

  • Specular > Shininess:用于反射的镜面反射指数。较低的值会增加反射的亮度并使它们更加漫射,而较高的值会使反射更加局部化。高值更适合看起来湿润的表面。

  • Texture > Filter:可以设置为覆盖纹理过滤模式,无论节点的属性设置为什么(或 Rendering > Textures > Canvas Textures > Default Texture Filter项目设置)。

  • Texture > Repeat:可以设置为覆盖纹理过滤模式,无论节点的属性设置为什么(或 Rendering > Textures > Canvas Textures > Default Texture Repeat项目设置)。

启用法线贴图后,您可能会注意到您的灯光似乎变弱了。要解决此问题,请增加PointLight2D 和 DirectionalLight2D 节点上的Height属性。您可能还想稍微增加灯光的 能量属性,以更接近启用法线贴图之前的灯光强度。

使用附加精灵作为 2D 灯的更快替代品

如果您在使用 2D 灯光时遇到性能问题,可能值得将其中一些替换为使用加法混合的 Sprite2D 节点。这特别适用于短暂的动态效果,例如子弹或爆炸。

附加精灵的渲染速度要快得多,因为它们不需要通过单独的渲染管道。此外,可以将此方法与 AnimatedSprite2D(或 Sprite2D + AnimationPlayer)一起使用,从而可以创建动画 2D“灯光”。

然而,与 2D 灯相比,附加精灵有一些缺点:

  • 与“实际”2D 照明相比,混合公式不准确。这在光线充足的区域通常不是问题,但这会阻止附加精灵正确地照亮完全黑暗的区域。

  • 附加精灵不能投射阴影,因为它们不是光。

  • 添加精灵会忽略其他精灵上使用的法线贴图和高光贴图。

要显示具有附加混合的精灵,请创建一个 Sprite2D 节点并为其分配一个纹理。在检查器中,向下滚动到CanvasItem > Material部分,展开它并单击Material属性 旁边的下拉菜单。选择New CanvasItemMaterial,点击新创建的材质进行编辑,然后将Blend Mode设置为Add

二维网格

介绍

在 3D 中,网格用于显示世界。在 2D 中,它们很少见,因为图像使用得更频繁。Godot 的 2D 引擎是一个纯二维引擎,所以它不能真正直接显示 3D 网格(虽然可以通过Viewport和 来完成ViewportTexture)。

也可以看看

如果您对在 2D 视口上显示 3D 网格感兴趣,请参阅使用视口作为纹理教程。

2D 网格是包含二维几何(Z 可以省略或忽略)而不是 3D 的网格。您可以尝试使用SurfaceTool代码自己创建它们并将它们显示在MeshInstance2D节点中。

目前,在编辑器中生成 2D 网格的唯一方法是将 OBJ 文件导入为网格,或将其从 Sprite2D 转换。

优化绘制的像素

在某些情况下,此工作流对于优化 2D 绘图很有用。当绘制具有透明度的大图像时,Godot 会将整个四边形绘制到屏幕上。仍然会绘制大的透明区域。

这会影响性能,尤其是在移动设备上,绘制非常大的图像(通常是屏幕大小),或将多个图像叠加在一起并具有大的透明区域(例如,使用 时)ParallaxBackground

转换为网格将确保只绘制不透明部分,其余部分将被忽略。

将 Sprite2D 转换为 2D 网格

Sprite2D您可以通过将 a 转换为 a 来利用此优化MeshInstance2D。从边缘包含大量透明度的图像开始,就像这棵树:

将其放入 a 中Sprite2D,然后从菜单中选择“Convert to 2D Mesh”:

将出现一个对话框,显示如何创建 2D 网格的预览:

对于许多情况,默认值已经足够了,但您可以根据需要更改增长和简化:

最后,按下按钮,您的 Sprite2D 将被替换:Convert 2D Mesh

二维精灵动画

介绍

在本教程中,您将学习如何使用 AnimatedSprite2D 类和 AnimationPlayer 创建 2D 动画角色。通常,当您创建或下载动画角色时,它会以两种方式之一出现:作为单独的图像或作为包含所有动画帧的单个 sprite 表。两者都可以在 Godot 中使用 AnimatedSprite2D 类进行动画处理。

首先,我们将使用AnimatedSprite2D为单个图像的集合设置动画。然后我们将使用此类为精灵表制作动画。最后,我们将学习另一种使用AnimationPlayerSprite2D 的Animation属性为精灵表设置动画的方法。

笔记

以下示例的艺术来自ansimuz | OpenGameArt.org和 tgfcoder。

使用 AnimatedSprite2D 的单个图像

在这个场景中,您有一组图像,每个图像都包含角色的一个动画帧。对于此示例,我们将使用以下动画:

您可以在此处下载图像: 2d_sprite_animation_assets.zip

解压缩图像并将它们放在项目文件夹中。使用以下节点设置场景树:

笔记

根节点也可以是Area2D或 RigidBody2D。动画仍将以相同的方式制作。动画完成后,您可以将形状分配给 CollisionShape2D。有关详细信息,请参阅 物理介绍。

现在选择AnimatedSprite2D并在其SpriteFrames属性中选择“New SpriteFrames”。

单击新的 SpriteFrames 资源,您将看到一个新面板出现在编辑器窗口的底部:

从左侧的文件系统停靠栏中,将 8 个单独的图像拖到 SpriteFrames 面板的中心部分。在左侧,将动画的名称从“默认”更改为“运行”。

使用Filter Animations输入右上角的“播放”按钮预览动画。您现在应该可以看到动画在视口中播放。但是,它有点慢。要解决此问题,请将SpriteFrames 面板中的速度 (FPS)设置更改为 10。

您可以通过单击“添加动画”按钮并添加其他图像来添加其他动画。

控制动画

动画完成后,您可以使用play()stop()方法通过代码控制动画。下面是一个简短的示例,可以在按住右箭头键的同时播放动画,并在松开该键时停止动画。

GD脚本C#
extends CharacterBody2D

@onready var _animated_sprite = $AnimatedSprite2D

func _process(_delta):
    if Input.is_action_pressed("ui_right"):
        _animated_sprite.play("run")
    else:
        _animated_sprite.stop()

带有 AnimatedSprite2D 的 Sprite 表

您还可以使用 class 轻松地从 sprite 表制作动画AnimatedSprite2D。我们将使用这个公共领域的 sprite 表:

右键单击图像并选择“图像另存为”以下载它,然后将图像复制到您的项目文件夹中。

以与之前使用单个图像时相同的方式设置场景树。选择AnimatedSprite2D并在其SpriteFrames属性中选择“New SpriteFrames”。

单击新的 SpriteFrames 资源。这次,当底部面板出现时,选择“从 Sprite 表添加帧”。

系统将提示您打开一个文件。选择你的精灵表。

将打开一个新窗口,显示您的精灵表。您需要做的第一件事是更改 Sprite 表中垂直和水平图像的数量。在这个 sprite 表中,我们有四个水平图像和两个垂直图像。

接下来,从精灵表中选择要包含在动画中的帧。我们将选择前四个,然后单击“添加 4 帧”以创建动画。

您现在将在底部面板的动画列表下看到您的动画。双击default,将动画名称改为jump。

最后,检查 SpriteFrames 编辑器上的播放按钮以查看您的青蛙跳跃!

带有 AnimationPlayer 的 Sprite 表

使用 sprite 表时可以设置动画的另一种方法是使用标准 Sprite2D节点来显示纹理,然后使用AnimationPlayer对纹理之间的变化进行动画处理。

考虑这个包含 6 帧动画的精灵表:

右键单击图像并选择“图像另存为”进行下载,然后将图像复制到您的项目文件夹中。

我们的目标是循环显示这些图像。从设置场景树开始:

笔记

根节点也可以是Area2D或 RigidBody2D。动画仍将以相同的方式制作。动画完成后,您可以将形状分配给 CollisionShape2D。有关详细信息,请参阅 物理介绍。

将 spritesheet 拖到 Sprite 的Texture属性中,您将看到整个工作表显示在屏幕上。要将其分割成单独的帧,请展开检查器中的动画部分并将Hframes设置为6。 HframesVframes是精灵表中水平和垂直帧的数量。

现在尝试更改Frame属性的值。您会看到它的范围从05并且 Sprite2D 显示的图像相应地发生变化。这是我们要制作动画的属性。

选择AnimationPlayer并单击“动画”按钮,然后单击“新建”。将新动画命名为“行走”。将动画长度设置为0.6并单击“循环”按钮,这样我们的动画就会重复。

现在选择Sprite2D节点并单击钥匙图标以添加新轨道。

继续在时间轴中的每个点(0.1默认为秒)添加帧,直到拥有从 0 到 5 的所有帧。您将看到实际出现在动画轨道中的帧:

在动画上按“播放”以查看其外观。

控制 AnimationPlayer 动画

play()与 AnimatedSprite2D 一样,您可以使用和方法通过代码控制动画stop()。同样,这是一个在按住右箭头键时播放动画并在释放键时停止动画的示例。

GD脚本C#
extends CharacterBody2D

@onready var _animation_player = $AnimationPlayer

func _process(_delta):
    if Input.is_action_pressed("ui_right"):
        _animation_player.play("walk")
    else:
        _animation_player.stop()

笔记

如果同时更新动画和单独的属性(例如,平台游戏可能会在角色开始“转动”动画时转动时更新 sprite 的h_flip/v_flip 属性),请务必记住play()不会立即应用。相反,它会在下次处理AnimationPlayer时应用。这可能最终出现在下一帧上,导致“故障”帧,其中应用了属性更改但没有应用动画。如果这证明是一个问题,调用后play(),您可以advance(0) 立即调用更新动画。

概括

这些示例说明了可以在 Godot 中用于 2D 动画的两个类。 AnimationPlayer比 稍微复杂一点AnimatedSprite2D,但它提供了额外的功能,因为您还可以为其他属性设置动画,例如位置或比例。该类AnimationPlayer也可以与AnimatedSprite2D. 尝试看看什么最适合您的需求。

二维粒子系统

介绍

粒子系统用于模拟复杂的物理效果,如火花、火焰、魔法粒子、烟雾、薄雾等。

这个想法是“粒子”以固定的间隔和固定的寿命发射。在其生命周期中,每个粒子都将具有相同的基本行为。使每个粒子与众不同并提供更有机外观的是与每个参数相关的“随机性”。从本质上讲,创建粒子系统意味着设置基础物理参数,然后为其添加随机性。

粒子节点

Godot 为 2D 粒子提供了两个不同的节点,GPUParticles2D 和CPUParticles2D。GPUParticles2D 更高级,使用 GPU 处理粒子效果。CPUParticles2D 是一个 CPU 驱动的选项,具有与 GPUParticles2D 相似的功能,但在使用大量粒子时性能较低。另一方面,CPUParticles2D 在低端系统或 GPU 瓶颈情况下可能表现更好。

虽然 GPUParticles2D 是通过ParticleProcessMaterial (并可选择使用自定义着色器)配置的,但匹配选项是通过 CPUParticles2D 中的节点属性提供的(轨迹设置除外)。

您可以将 GPUParticles2D 节点转换为 CPUParticles2D 节点,方法是单击检查器中的节点,然后在 3D 编辑器视口顶部的工具栏中选择Particles > Convert to CPUParticles2D 。

本教程的其余部分将使用 GPUParticles2D 节点。首先,将 GPUParticles2D 节点添加到场景中。创建该节点后,您会注意到只创建了一个白点,并且在场景停靠栏中的 GPUParticles2D 节点旁边有一个警告图标。这是因为节点需要 ParticleProcessMaterial 才能运行。

粒子处理材质

要将处理材料添加到您的粒子节点,请转到您的检查器面板中。单击 旁边的框,然后从下拉菜单中选择。Process MaterialMaterialNew ParticleProcessMaterial

您的 GPUParticles2D 节点现在应该向下发射白点。

质地

粒子系统使用单个纹理(将来可能会通过 spritesheet 扩展到动画纹理)。纹理通过相关的纹理属性设置:

时间参数

寿命

每个粒子存活的时间(以秒为单位)。当生命周期结束时,将创建一个新粒子来替换它。

寿命:0.5

寿命:4.0

一枪

启用后,GPUParticles2D 节点将发射一次所有粒子,然后再也不会发射。

预处理

粒子系统从发射零粒子开始,然后开始发射。这在加载场景和火炬、雾等系统时可能会带来不便。在您进入的那一刻就开始发光。预处理用于让系统在第一次实际绘制之前处理给定的秒数。

速度秤

速度刻度的默认值为1,用于调整粒子系统的速度。降低该值将使粒子变慢,而增加该值将使粒子更快。

爆发力

如果 lifetime 是1并且有 10 个粒子,则意味着每 0.1 秒发射一个粒子。explosiveness 参数改变了这一点,并强制粒子一起发射。范围是:

  • 0:定期发射粒子(默认值)。

  • 1:同时发射所有粒子。

中间的值也是允许的。此功能对于创建爆炸或突然爆发的粒子很有用:

随机性

所有物理参数都可以随机化。随机值范围从0到 1. 随机化参数的公式为:

initial_value = param_value + param_value * randomness

固定帧率

此设置可用于将粒子系统设置为以固定 FPS 渲染。例如,将值更改为2将使粒子以每秒 2 帧的速度渲染。请注意,这不会减慢粒子系统本身的速度。

分数三角洲

这可用于打开或关闭 Fract Delta。

绘图参数

可见性矩形

可见性矩形控制屏幕上粒子的可见性。如果这个矩形在视口之外,引擎将不会在屏幕上渲染粒子。

矩形的WH属性分别控制它的宽度和高度。和属性控制矩形左上角相对于粒子发射器的位置XY

您可以使用 2d 视图上方的工具栏让 Godot 自动生成可见性矩形。为此,选择 GPUParticles2D 节点并单击。Godot 将模拟 Particles2D 节点发射粒子几秒钟,并设置矩形以适合粒子所采用的表面。Particles > Generate Visibility Rect

您可以使用该选项控制发射持续时间。最大值为 25 秒。如果您需要更多时间让粒子四处移动,您可以临时更改Particles2D 节点上的持续时间。Generation Time (sec)preprocess

当地坐标

默认情况下,此选项处于启用状态,这意味着粒子发射到的空间是相对于节点的。如果移动节点,则所有粒子都会随之移动:

如果禁用,粒子将发射到全局空间,这意味着如果移动节点,已经发射的粒子不受影响:

开奖顺序

这控制绘制单个粒子的顺序。Index 表示粒子是根据它们的发射顺序绘制的(默认)。 Lifetime表示它们是按照剩余寿命的顺序绘制的。

ParticleProcessMaterial 设置

方向

这是粒子发射的基本方向。默认设置是 使粒子向右发射。但是,在默认重力设置下,粒子将直接向下移动。Vector3(1, 0, 0)

要使此属性引人注目,您需要一个大于 0 的初始速度。在这里,我们将初始速度设置为 40。您会注意到粒子向右发射,然后由于重力而下降

传播

此参数是以度为单位的角度,它将在任一方向上随机添加到 base Direction180将向所有方向 (+/- 180) 发射散布。为了传播做任何事情,“初始速度”参数必须大于 0。

平面度

此属性仅对 3D 粒子有用。

重力

应用于每个粒子的重力。

初始速度

初始速度是发射粒子的速度(以像素/秒为单位)。速度稍后可能会因重力或其他加速度而改变(如下所述)。

角速度

角速度是应用于粒子的初始角速度。

自旋速度

自旋速度是粒子围绕其中心旋转的速度(以度/秒为单位)。

轨道速度

轨道速度用于使粒子围绕其中心旋转。

直线加速

应用于每个粒子的线性加速度。

径向加速度

如果此加速度为正,则粒子会加速远离中心。如果是负数,它们就会被它吸收。

切向加速度

此加速度将使用到中心的切线向量。结合径向加速度可以起到很好的效果。

减震

阻尼对粒子施加摩擦力,迫使它们停止。它对火花或爆炸特别有用,这些火花或爆炸通常以高线速度开始,然后随着它们的消退而停止。

角度

确定粒子的初始角度(以度为单位)。此参数最有用的是随机化。

规模

确定粒子的初始比例。

颜色

用于改变发射粒子的颜色。

色调变化

Variation值设置应用于每个粒子的初始色调变化。该值控制色调变化的随机性比率。Variation Random

发射形状

ParticleProcessMaterials 允许您设置一个 Emission Mask,它决定了粒子发射的区域和方向。这些可以从项目中的纹理生成。

确保设置了 ParticleProcessMaterial,并选择了 GPUParticles2D 节点。“粒子”菜单应该出现在工具栏中:

打开它并选择“Load Emission Mask”:

然后选择要用作蒙版的纹理:

将出现一个包含多个设置的对话框。

发射掩模

可以从纹理生成三种类型的发射遮罩:

  • Solid Pixels:粒子将从纹理的任何区域产生,不包括透明区域。

  • 边界像素:粒子将从纹理的外边缘产生。

  • Directed Border Pixels:与 Border Pixels 类似,但向蒙版添加了额外信息,使粒子能够从边界发射出去。请注意,需要设置遗嘱才能使用它。Initial Velocity

发射颜色

Capture from Pixel将使粒子在其生成点继承遮罩的颜色。

单击“确定”后,将生成遮罩并将其设置为 ParticleProcessMaterial,位于以下部分:Emission Shape

此部分中的所有值都是由“加载发射掩码”菜单自动生成的,因此通常应保留它们。

笔记

不应将图像添加到或直接添加。应始终使用“加载发射掩码”菜单。Point TextureColor Texture

二维抗锯齿

也可以看看

Godot 还支持 3D 渲染中的抗锯齿。这在3D 抗锯齿页面上有介绍 。

介绍

由于分辨率有限,以 2D 渲染的场景可能会出现锯齿现象。这些伪影通常以几何边缘上的“阶梯”效果的形式出现,并且在使用Line2D、 Polygon2DTextureProgressBar等节点时最为明显。 对于不支持抗锯齿的方法,2D 中的自定义绘图也可能有锯齿现象。

在下面的示例中,您可以注意到边缘是如何呈现块状外观的:

图像通过最近邻域滤波缩放 2 倍,使混叠更加明显。

为了解决这个问题,Godot 支持多种在 2D 渲染上启用抗锯齿的方法。

Line2D 和自定义绘图中的抗锯齿属性

这是推荐的方法,因为它在大多数情况下对性能的影响较小。

Line2D 具有Antialiased属性,您可以在检查器中启用该属性。此外,用于在 2D 中自定义绘图的几种方法支持可选 参数,可以在调用函数时antialiased设置该参数。true

这些方法不需要启用 MSAA,这使得它们的基线 性能成本较低。换句话说,如果您在某个时候不绘制任何抗锯齿几何图形,则不会永久增加成本。

这些抗锯齿方法的缺点是它们通过生成额外的几何体来工作。如果您要生成每帧都更新的复杂 2D 几何体,这可能是一个瓶颈。此外,Polygon2D、TextureProgressBar 和一些自定义绘图方法不具有抗锯齿属性。对于这些节点,您可以改用 2D 多重采样抗锯齿。

多样本抗锯齿 (MSAA)

在 2D 中启用 MSAA 之前,了解 MSAA 将在什么上运行很重要。2D 中的 MSAA 遵循与 3D 中类似的限制。虽然它不会引入任何模糊,但它的应用范围是有限的。2D MSAA的主要应用是:

  • 几何边缘,例如线和多边形绘图。

  • 精灵边缘仅适用于接触纹理边缘之一的像素。这适用于线性和最近邻过滤。使用图像透明度创建的 Sprite 边缘不受 MSAA 影响。

MSAA 的缺点是它仅在边缘上运行。这是因为 MSAA 增加了覆盖样本的数量,但没有增加颜色样本的数量 。然而,由于颜色样本的数量没有增加,片段着色器仍然只为每个像素运行一次。因此,MSAA 不会以任何方式影响以下类型的别名:

  • 最近邻过滤纹理(像素艺术)中的混叠。

  • 由自定义 2D 着色器引起的混叠。

  • 使用 Light2D 时出现镜面反射混叠。

  • 字体渲染中的别名。

通过更改渲染 > 抗锯齿 > 质量 > MSAA 2D设置的值,可以在项目设置中启用 MSAA 。重要的是更改MSAA 2D设置的值而不是MSAA 3D,因为它们是完全独立的设置。

无抗锯齿(左)和各种 MSAA 级别(右)之间的比较。左上角包含一个 Line2D 节点,右上角包含 2 个 TextureProgressBar 节点。底部包含 8 个像素艺术精灵,其中 4 个接触边缘(绿色背景),另外 4 个不接触边缘(Godot 徽标):

  

自定义二维绘图

介绍

Godot 有节点来绘制精灵、多边形、粒子和各种东西。对于大多数情况,这就足够了。如果没有节点可以绘制您需要的特定内容,您可以使任何 2D 节点(例如,基于Control或 Node2D)绘制自定义命令。

在 2D 节点中自定义绘图非常有用。以下是一些用例:

  • 绘制现有节点无法执行的形状或逻辑,例如带有轨迹的图像或特殊的动画多边形。

  • 与节点不兼容的可视化,例如俄罗斯方块板。(俄罗斯方块示例使用自定义绘制函数来绘制块。)

  • 绘制大量简单的对象。自定义绘图避免了使用大量节点的开销,可能会降低内存使用量并提高性能。

  • 制作自定义 UI 控件。有很多可用的控件,但是当您有不寻常的需求时,您可能需要自定义控件。

绘画

将脚本添加到任何CanvasItem 派生节点,例如Control或 Node2D。然后覆盖该_draw()功能。

GD脚本C#
extends Node2D

func _draw():
    # Your draw commands here
    pass

绘图命令在CanvasItem 类参考中进行了描述。有很多。

更新中

_draw()函数只被调用一次,然后绘制命令被缓存并记住,因此不需要进一步调用。

如果由于状态或其他更改而需要重新绘制,请 在同一节点中调用CanvasItem.queue_redraw()_draw()并进行新的调用。

这是一个稍微复杂一点的例子,一个纹理变量,如果被修改将被重新绘制:

GD脚本C#
extends Node2D

export (Texture) var texture setget _set_texture

func _set_texture(value):
    # If the texture variable is modified externally,
    # this callback is called.
    texture = value  # Texture was changed.
    queue_redraw()  # Trigger a redraw of the node.

func _draw():
    draw_texture(texture, Vector2())

在某些情况下,可能需要绘制每一帧。为此,queue_redraw()_process()回调中调用,如下所示:

GD脚本C#
extends Node2D

func _draw():
    # Your draw commands here
    pass

func _process(delta):
    queue_redraw()

坐标

绘图 API 使用 CanvasItem 的坐标系统,不一定是像素坐标。这意味着它使用在应用 CanvasItem 的变换后创建的坐标空间。此外,您可以使用draw_set_transform或 draw_set_transform_matrix在其上应用自定义转换 。

使用时draw_line,应考虑线条的宽度。当使用奇数大小的宽度时,位置应移动 以0.5保持线居中,如下所示。

GD脚本C#
func _draw():
    draw_line(Vector2(1.5, 1.0), Vector2(1.5, 4.0), Color.GREEN, 1.0)
    draw_line(Vector2(4.0, 1.0), Vector2(4.0, 4.0), Color.GREEN, 2.0)
    draw_line(Vector2(7.5, 1.0), Vector2(7.5, 4.0), Color.GREEN, 3.0)

这同样适用于draw_rect方法 with 。filled = false

GD脚本C#
func _draw():
    draw_rect(Rect2(1.0, 1.0, 3.0, 3.0), Color.GREEN)
    draw_rect(Rect2(5.5, 1.5, 2.0, 2.0), Color.GREEN, false, 1.0)
    draw_rect(Rect2(9.0, 1.0, 5.0, 5.0), Color.GREEN)
    draw_rect(Rect2(16.0, 2.0, 3.0, 3.0), Color.GREEN, false, 2.0)

示例:绘制圆弧

我们现在将使用 Godot 引擎的自定义绘图功能来绘制 Godot 未提供的功能。例如,Godot 提供了一个draw_circle()绘制整个圆的函数。但是,绘制圆的一部分呢?您将必须编写一个函数来执行此操作并自己绘制。

圆弧功能

圆弧由其支撑圆参数定义,即圆心位置和半径。然后弧本身由它开始的角度和它停止的角度定义。这些是我们必须提供给绘图函数的 4 个参数。我们还将提供颜色值,因此我们可以根据需要绘制不同颜色的弧。

基本上,在屏幕上绘制一个形状需要将其分解为一定数量的点,这些点从一个点连接到另一个点。可以想象,你的形状由越多的点组成,看起来越光滑,但在加工成本方面也会越重。一般来说,如果你的形状很大(或者在 3D 中,靠近相机),它需要绘制更多的点而不是有棱角的。相反,如果你的形状很小(或者在 3D 中,远离相机),你可以减少它的点数以节省处理成本;这称为细节级别 (LOD)。在我们的示例中,无论半径如何,我们都将简单地使用固定数量的点。

GD脚本C#
func draw_circle_arc(center, radius, angle_from, angle_to, color):
    var nb_points = 32
    var points_arc = PackedVector2Array()

    for i in range(nb_points + 1):
        var angle_point = deg_to_rad(angle_from + i * (angle_to-angle_from) / nb_points - 90)
        points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)

    for index_point in range(nb_points):
        draw_line(points_arc[index_point], points_arc[index_point + 1], color)

还记得我们的形状必须分解成的点数吗?我们将nb_points变量中的这个数字固定为值32。然后,我们初始化一个空的 PackedVector2Array,它只是一个Vector2s 数组。

下一步包括计算构成弧的这 32 个点的实际位置。这是在第一个 for 循环中完成的:我们迭代要计算位置的点数,再加上最后一个点。我们首先确定每个点的角度,介于起始角度和结束角度之间。

每个角度减少 90° 的原因是我们将使用三角函数(你知道,余弦和正弦的东西......)计算每个角度的 2D 位置。但是, cos()使用sin()弧度,而不是度数。0°(0 弧度)的角度从 3 点开始,虽然我们想从 12 点开始计数。所以我们将每个角度减少 90°,以便从 12 点钟开始计数。

以一定角度(以弧度为单位)位于圆上的点的实际位置angle由 给出。由于和返回值介于 -1 和 1 之间,因此该位置位于半径为 1 的圆上。要使该位置位于半径为 的支持圆上,我们只需将位置乘以。最后,我们需要将我们的支持圈定位在该位置,这是通过将其添加到我们的价值来执行的。最后,我们将点插入到先前定义的 which 中。Vector2(cos(angle), sin(angle))cos()sin()radiusradiuscenterVector2PackedVector2Array

现在,我们需要实际得出我们的观点。可以想象,我们不会简单地画出 32 个点:我们需要画出每个点之间的所有内容。我们可以使用以前的方法自己计算每个点,然后一个一个地画出来。但这太复杂且效率低下(除非明确需要),因此我们只是在每对点之间画线。除非我们的支持圆的半径很大,否则一对点之间的每条线的长度永远不会长到足以看到它们。如果发生这种情况,我们只需要增加点数即可。

在屏幕上绘制圆弧

我们现在有一个在屏幕上绘制东西的功能;是时候在_draw()函数内部调用它了:

GD脚本C#
func _draw():
    var center = Vector2(200, 200)
    var radius = 80
    var angle_from = 75
    var angle_to = 195
    var color = Color(1.0, 0.0, 0.0)
    draw_circle_arc(center, radius, angle_from, angle_to, color)

结果:

圆弧多边形函数

我们可以更进一步,不仅可以编写一个函数来绘制由圆弧定义的圆盘的平面部分,还可以绘制其形状。该方法与之前完全相同,只是我们绘制的是多边形而不是直线:

GD脚本C#
func draw_circle_arc_poly(center, radius, angle_from, angle_to, color):
    var nb_points = 32
    var points_arc = PackedVector2Array()
    points_arc.push_back(center)
    var colors = PackedColorArray([color])

    for i in range(nb_points + 1):
        var angle_point = deg_to_rad(angle_from + i * (angle_to - angle_from) / nb_points - 90)
        points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)
    draw_polygon(points_arc, colors)

动态自定义绘图

好了,我们现在可以在屏幕上绘制自定义内容了。但是,它是静态的;让我们让这个形状围绕中心转动。这样做的解决方案是随时间更改 angle_from 和 angle_to 值。对于我们的示例,我们将简单地将它们增加 50。这个增量值必须保持不变,否则旋转速度将相应改变。

首先,我们必须在脚本顶部使 angle_from 和 angle_to 变量成为全局变量。另请注意,您可以将它们存储在其他节点中并使用get_node().

GD脚本C#
extends Node2D

var rotation_angle = 50
var angle_from = 75
var angle_to = 195

我们在 _process(delta) 函数中改变这些值。

我们还在这里增加了 angle_from 和 angle_to 的值。但是,我们不能忘记wrap()0 到 360° 之间的结果值!也就是说,如果角度是 361°,那么它实际上是 1°。如果你不包装这些值,脚本将正常工作,但角度值会随着时间的推移变得越来越大,直到它们达到 Godot 可以管理的最大整数值 ( ) 。发生这种情况时,Godot 可能会崩溃或产生意外行为。2^31 - 1

最后,我们一定不要忘记调用函数queue_redraw(),它会自动调用_draw(). 这样,您可以控制何时刷新框架。

GD脚本C#
func _process(delta):
    angle_from += rotation_angle
    angle_to += rotation_angle

    # We only wrap angles when both of them are bigger than 360.
    if angle_from > 360 and angle_to > 360:
        angle_from = wrapf(angle_from, 0, 360)
        angle_to = wrapf(angle_to, 0, 360)
    queue_redraw()

另外,不要忘记修改函数_draw()以使用这些变量:

GD脚本C#
func _draw():
   var center = Vector2(200, 200)
   var radius = 80
   var color = Color(1.0, 0.0, 0.0)

   draw_circle_arc( center, radius, angle_from, angle_to, color )

我们跑吧!它有效,但电弧旋转得快得离谱!怎么了?

原因是您的 GPU 实际上正在尽可能快地显示帧。我们需要用这个速度“规范化”绘图;为此,我们必须使用函数delta的参数_process()delta包含两个最后渲染帧之间经过的时间。它通常很小(大约 0.0003 秒,但这取决于您的硬件),因此使用来delta控制您的绘图可确保您的程序在每个人的硬件上以相同的速度运行。

在我们的例子中,我们只需要 在函数rotation_angle中将变量乘以。这样,我们的2个角度会增加一个小很多的值,这个值直接取决于渲染速度。delta_process()

GD脚本C#
func _process(delta):
    angle_from += rotation_angle * delta
    angle_to += rotation_angle * delta

    # We only wrap angles when both of them are bigger than 360.
    if angle_from > 360 and angle_to > 360:
        angle_from = wrapf(angle_from, 0, 360)
        angle_to = wrapf(angle_to, 0, 360)
    queue_redraw()

我们再跑一次!这一次,旋转显示正常!

抗锯齿绘图

Godot 在draw_line中提供方法参数 以启用抗锯齿,但并非所有自定义绘图方法都提供此antialiased 参数。

对于不提供antialiased参数的自定义绘图方法,您可以改为启用 2D MSAA,这会影响整个视口中的渲染。这提供了高质量的抗锯齿,但性能成本更高且仅针对特定元素。有关详细信息,请参阅2D 抗锯齿。

工具

在编辑器中运行节点时,可能还需要绘制您自己的节点。这可以用作某些功能或行为的预览或可视化。有关详细信息,请参阅在编辑器中运行代码。

二维运动概述

介绍

每个初学者都遇到过:“我如何移动我的角色?” 根据您制作的游戏风格,您可能有特殊要求,但通常大多数 2D 游戏中的移动都是基于少量设计。

我们将在这些示例中使用CharacterBody2D,但这些原则也适用于其他节点类型(Area2D、RigidBody2D)。

设置

下面的每个示例都使用相同的场景设置。从有两个孩子的 a 开始CharacterBody2DSprite2DCollisionShape2D。您可以为 Sprite2D 的纹理使用 Godot 图标(“icon.png”)或使用您拥有的任何其他 2D 图像。

打开并选择“输入地图”选项卡。添加以下输入操作(详见InputEvent):Project -> Project Settings

8向运动

在这种情况下,您希望用户按下四个方向键(上/左/下/右或 W/A/S/D)并向选定的方向移动。“8向移动”这个名字来源于这样一个事实,即玩家可以通过同时按下两个键来沿对角线移动。

在角色身上添加脚本,添加如下代码:

GD脚本C#
extends CharacterBody2D

@export var speed = 400

func get_input():
    var input_direction = Input.get_vector("left", "right", "up", "down")
    velocity = input_direction * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

get_input()函数中,我们使用Input get_vector()检查四个关键事件并求和返回一个方向向量。

然后我们可以通过将这个长度为 的方向向量1乘以我们想要的速度来设置我们的速度。

笔记

如果上面的代码在您按下按键时没有执行任何操作,请仔细检查您是否已按照本教程的设置部分所述正确设置输入操作 。

旋转+移动

这种类型的运动有时被称为“小行星式”,因为它类似于经典街机游戏的工作方式。向左/向右按可旋转角色,而按向上/向下可使其朝任何方向向前或向后移动。

GD脚本C#
extends CharacterBody2D

@export var speed = 400
@export var rotation_speed = 1.5

var rotation_direction = 0

func get_input():
    rotation_direction = Input.get_axis("left", "right")
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    rotation += rotation_direction * rotation_speed * delta
    move_and_slide()

这里我们添加了两个变量来跟踪我们的旋转方向和速度。旋转直接应用于身体的rotation属性。

为了设置速度,我们使用 body's transform.x,它是一个指向身体“向前”方向的向量,并将其乘以速度。

旋转+移动(鼠标)

这种运动风格是前一种运动的变体。这一次,方向是由鼠标位置而不是键盘设置的。角色将始终“注视”鼠标指针。然而,前向/后向输入保持不变。

GD脚本C#
extends CharacterBody2D

@export var speed = 400

func get_input():
    look_at(get_global_mouse_position())
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

这里我们使用Node2D look_at()方法将玩家指向鼠标的位置。没有这个功能,你可以通过像这样设置角度来获得相同的效果:

GD脚本C#
rotation = get_global_mouse_position().angle_to_point(position)

点击并移动

最后一个示例仅使用鼠标来控制角色。单击屏幕将使玩家移动到目标位置。

GD脚本C#
extends CharacterBody2D

@export var speed = 400

var target = position

func _input(event):
    if event.is_action_pressed("click"):
        target = get_global_mouse_position()

func _physics_process(delta):
    velocity = position.direction_to(target) * speed
    # look_at(target)
    if position.distance_to(target) > 10:
        move_and_slide()

请注意distance_to()我们在移动之前所做的检查。如果没有这个测试,身体会在到达目标位置时“抖动”,因为它略微移动超过该位置并试图向后移动,只是移动得太远并重复。

如果您愿意,取消注释该look_at()线也会使身体指向其运动方向。

提示

这种技术也可以用作“跟随”角色的基础。该target位置可以是您要移动到的任何对象的位置。

概括

您可能会发现这些代码示例可用作您自己项目的起点。随意使用它们并试验它们,看看你能做什么。

您可以在此处下载此示例项目: 2d_movement_starter.zip

使用 TileSet

介绍

瓦片地图是用于创建游戏布局的瓦片网格。使用TileMap节点设计关卡有几个好处。首先,它们允许您通过将图块“绘制”到网格上来绘制布局,这比一个接一个地放置单个Sprite2D节点要快得多。其次,它们允许更大的级别,因为它们针对绘制大量图块进行了优化。最后,它们允许您通过碰撞、遮挡和导航形状为您的图块添加更多功能。

要使用 tilemaps,您需要先创建一个 TileSet。TileSet 是可以放置在 TileMap 节点中的瓦片集合。创建 TileSet 后,您将能够使用 TileMap 编辑器放置它们。

要遵循本指南,您将需要一个包含您的图块的图像,其中每个图块都具有相同的大小(大对象可以分成几个图块)。此图像称为tilesheet。瓷砖不一定是正方形:它们可以是矩形、六边形或等距(伪 3D 透视)。

创建一个新的 TileSet

使用瓷砖表

该演示将使用从Kenney 的“抽象平台游戏”包中获取的以下图块 。我们将使用集合中的这个特定图块表:

具有 64×64 tiles 的 tilesheet。学分:肯尼

创建一个新的TileMap节点,然后选择它并在检查器中创建一个新的 TileSet 资源:

在 TileMap 节点中创建新的 TileSet 资源

创建 TileSet 资源后,单击值以在检查器中展开它。默认的拼贴形状是正方形,但您也可以选择等距、半偏移正方形或六边形(取决于拼贴图像的形状)。如果使用方形以外的图块形状,您可能还需要调整图块布局图块偏移轴属性。最后, 如果您希望按瓷砖坐标裁剪瓷砖,启用渲染 > UV 裁剪属性可能会有用。这可确保图块无法在图块表上的分配区域之外绘制。

在检查器中将图块大小设置为 64×64 以匹配示例图块表:

将图块大小设置为 64×64 以匹配示例图块表

如果依靠自动创建图块(就像我们将要在这里做的那样),您必须在创建图集之前设置图块大小。图集将确定可以将 tilesheet 中的哪些图块添加到 TileMap 节点(因为并非图像的每个部分都可能是有效的图块)。

打开编辑器底部的TileSet面板,然后点击左下角的“+”图标添加一个新的图集:

使用底部面板在 TileSet 资源中创建新图集

创建图集后,您必须为其分配一个 tilesheet 纹理。这可以通过在底部面板的左列中选择它来完成,然后单击Texture属性的值并选择Quick Load(或Load)。使用出现的文件对话框指定图像文件的路径。

在新创建的 TileSet atlas 中加载 tilesheet 图像

指定有效图像后,系统会询问您是否自动创建图块。回答

根据 tilesheet 图像内容自动创建 tiles

这将根据您之前在 TileSet 资源中指定的图块大小自动创建图块。这大大加快了初始磁贴设置。

笔记

使用基于图像内容的自动切片生成时,完全透明的切片表部分不会生成切片。

如果瓷砖表中有您不希望出现在地图集中的瓷砖,请选择瓷砖集预览顶部的橡皮擦工具,然后单击您希望删除的瓷砖:

使用橡皮擦工具从 TileSet 图集中删除不需要的图块

您还可以右键单击图块并选择删除,作为橡皮擦工具的替代方法。

提示

与在 2D 和 TileMap 编辑器中一样,您可以使用鼠标中键或右键在 TileSet 面板上平移,并使用鼠标滚轮或左上角的按钮进行缩放。

如果您希望从单个 TileSet 的多个 tilesheet 图像中获取 tiles,请在继续之前创建额外的图集并为每个图集分配纹理。也可以通过这种方式为每个图块使用一个图像(尽管建议使用图块表以获得更好的可用性)。

您可以在中间列中调整图集的属性:

在专用检查器(TileSet 面板的一部分)中调整 TileSet 图集属性

可以在图集上调整以下属性:

  • ID:标识符(在这个 TileSet 中是唯一的),用于排序。

  • 名称:地图集的人类可读名称。出于组织目的,此处使用描述性名称(例如“地形”、“装饰”等)。

  • 边距:图像边缘的边距不应被选为图块(以像素为单位)。如果您下载边缘有边距的图块图像(例如,用于归属),增加此值可能很有用。

  • Separation:图集上每个图块之间的间距(以像素为单位)。如果您使用的 tilesheet 图像包含参考线(例如每个图块之间的轮廓),则增加此值会很有用。

  • Texture Region Size:图集上每个图块的大小(以像素为单位)。在大多数情况下,这应该与 TileMap 属性中定义的图块大小相匹配(尽管这不是绝对必要的)。

  • 使用纹理填充:如果选中,则在每个图块周围添加一个 1 像素的透明边缘,以防止在启用过滤时出现纹理渗色。建议启用此选项,除非您因纹理填充而遇到渲染问题。

请注意,更改纹理边距、分隔和区域大小可能会导致图块丢失(因为其中一些图块将位于地图集图像的坐标之外)。要从图块表自动重新生成图块,请使用 TileSet 编辑器顶部的三个垂直点菜单按钮并选择 在非透明纹理区域中创建图块

更改图集属性后自动重新创建切片

使用场景集合

从 Godot 4.0 开始,您可以将实际场景放置为图块。这允许您将任何节点集合用作图块。例如,您可以使用场景图块来放置游戏元素,例如玩家可以与之互动的商店。您还可以使用场景图块来放置 AudioStreamPlayer2D(用于环境声音)、粒子效果等。

警告

与地图集相比,场景图块具有更大的性能开销,因为每个场景都是针对每个放置的图块单独实例化的。

建议在必要时仅使用场景图块。要在没有任何高级操作的情况下在图块中绘制精灵, 请改用图集

对于此示例,我们将创建一个包含 CPUParticles2D 根节点的场景。将该场景保存到场景文件(与包含 TileMap 的场景分开),然后切换到包含 TileMap 节点的场景。打开 TileSet 编辑器,并在左侧栏中创建一个新的Scenes Collection :

在 TileSet 编辑器中创建场景集合

创建场景集合后,您可以根据需要在中间栏中为场景集合输入一个描述性名称。选择这个场景集合然后创建一个新的场景槽:

在 TileSet 编辑器中选择场景集合后创建场景图块

在右列中选择这个场景槽,然后使用快速加载(或 加载)加载包含粒子的场景文件:

创建场景槽,然后在 TileSet 编辑器中将场景文件加载到其中

您现在在 TileSet 中有了一个场景图块。切换到 TileMap 编辑器后,您将能够从场景集合中选择它并像绘制任何其他图块一样对其进行绘制。

将多个地图集合并为一个地图集

在单个 TileSet 资源中使用多个图集有时很有用,但在某些情况下也可能很麻烦(尤其是在每个图块使用一张图像的情况下)。Godot 允许您将多个图集合并为一个图集,以便于组织。

为此,您必须在 TileSet 资源中创建多个地图集。使用位于地图集列表底部的“三个垂直点”菜单按钮,然后选择打开地图集合并工具

创建多个图集后打开图集合并工具

这将打开一个对话框,您可以在其中通过按住 Shift或Ctrl单击多个元素来选择多个图集:

使用图集合并工具对话框

选择Merge将选定的图集合并为单个图集图像(转换为 TileSet 中的单个图集)。未合并的图集将在 TileSet 中删除,但原始图集图像将保留在文件系统中。如果您不想从 TileSet 资源中删除未合并的地图集,请改为选择合并(保留原始地图集)

提示

TileSet 具有一个瓦片代理系统。瓦片代理是一个映射表,它允许使用给定的 TileSet 通知 TileMap 一组给定的瓦片标识符应该被另一组替换。

合并不同的地图集时会自动设置 Tile 代理,但也可以手动设置它们,这要归功于管理 Tile Proxies对话框,您可以使用上面提到的“三个垂直点”菜单访问。

当您更改图集 ID 或想要将一个图集中的所有图块替换为另一个图集中的图块时,手动创建图块代理可能很有用。请注意,在编辑 TileMap 时,您可以用相应的映射值替换所有单元格。

向 TileSet 添加碰撞、导航和遮挡

我们现在已经成功地创建了一个基本的 TileSet。我们现在可以开始在 TileMap 节点中使用,但它目前缺少任何形式的碰撞检测。这意味着玩家和其他物体可以直接穿过地板或墙壁。

如果您使用2D 导航,您还需要为图块定义导航多边形以生成代理可用于寻路的导航网格。

最后,如果您使用2D 灯光和阴影或 GPUParticles2D,您可能还希望您的 TileSet 能够投射阴影并与粒子碰撞。这需要为 TileSet 上的“实体”图块定义遮挡多边形。

为了能够为每个图块定义碰撞、导航和遮挡形状,您需要先为 TileSet 资源创建一个物理层、导航层或遮挡层。为此,选择 TileMap 节点,单击检查器中的 TileSet 属性值对其进行编辑,然后展开物理层并选择 添加元素

在 TileSet 资源检查器中创建物理层(在 TileMap 节点内)

如果您还需要导航支持,现在是创建导航层的好时机:

在 TileSet 资源检查器中创建导航层(在 TileMap 节点内)

如果您需要对光多边形遮挡物的支持,现在是创建遮挡层的好时机:

在 TileSet 资源检查器中创建遮挡层(在 TileMap 节点内)

笔记

本教程中的后续步骤专门用于创建碰撞多边形,但导航和遮挡的过程非常相似。它们各自的多边形编辑器的行为方式相同,因此为简洁起见不再重复这些步骤。

唯一需要注意的是,图块的遮挡多边形属性是 图集检查器中渲染子部分的一部分。确保展开此部分,以便您可以编辑多边形。

创建物理层后,您可以访问TileSet 图集检查器中的物理层部分:

在选择模式下打开碰撞编辑器

F当 TileSet 编辑器处于焦点状态时,您可以通过按下来快速创建一个矩形碰撞形状。如果键盘快捷键不起作用,请尝试单击多边形编辑器周围的空白区域以将其聚焦:

通过按下使用默认的矩形碰撞形状F

在此瓷砖碰撞编辑器中,您可以使用所有 2D 多边形编辑工具:

  • 使用多边形上方的工具栏在创建新多边形、编辑现有多边形和移除多边形上的点之间切换。“三个垂直点”菜单按钮提供了额外的选项,例如旋转和翻转多边形。

  • 通过单击并拖动两点之间的线来创建新点。

  • 通过右键单击点(或使用上述删除工具并单击鼠标左键)来删除它。

  • 通过中键单击或右键单击在编辑器中平移。(右键平移只能在附近没有点的区域使用。)

您可以使用默认矩形形状通过删除其中一个点来快速创建三角形碰撞形状:

通过右键单击其中一个角将其删除来创建三角形碰撞形状

您还可以通过添加更多点将矩形用作更复杂形状的基础:

为复杂的瓷砖形状绘制自定义碰撞

提示

如果你有一个大的 tileset,为每个 tile 单独指定碰撞可能会花费很多时间。尤其如此,因为 TileMap 往往有许多具有常见碰撞模式的图块(例如实心块或 45 度斜坡)。要将相似的碰撞形状快速应用于多个图块,请使用 一次将属性分配给多个图块的功能。

将自定义元数据分配给 TileSet 的图块

您可以使用自定义数据层在每个图块的基础上分配自定义数据。这对于存储特定于您的游戏的信息很有用,例如当玩家触摸时瓷砖应该造成的伤害,或者是否可以使用武器摧毁瓷砖。

数据与 TileSet 中的图块相关联:放置的图块的所有实例都将使用相同的自定义数据。如果您需要创建具有不同自定义数据的磁贴变体,这可以通过创建替代磁贴并仅更改替代磁贴的自定义数据来完成。

在 TileSet 资源检查器中创建自定义数据层(在 TileMap 节点内)

具有游戏特定属性的已配置自定义数据层示例

您可以在不破坏现有元数据的情况下重新排序自定义数据:TileSet 编辑器将在重新排序自定义数据属性后自动更新。

请注意,在编辑器中,属性名称不会出现(仅显示它们的索引,这与它们定义的顺序相匹配)。例如,对于上面显示的自定义数据层示例,我们正在分配一个图块以将 damage_per_second元数据设置为25并将destructible元数据设置为false

在选择模式下在 TileSet 编辑器中编辑自定义数据

Tile 属性绘制 也可用于自定义数据:

使用 tile 属性绘制在 TileSet 编辑器中分配自定义数据

创建地形集(自动拼接)

笔记

此功能以与 Godot 3.x 中的自动平铺不同的形式实现。Terrains 本质上是 autotiles 的更强大的替代品。与 autotiles 不同,terrain 可以支持从一个地形到另一个地形的转换,因为一个 tile 可以同时定义多个地形。

与以前不同,自动图块是一种特定类型的图块,地形只是分配给图集图块的一组属性。然后,这些属性由专用的 TileMap 绘画模式使用,该模式以智能方式选择具有地形数据的图块。这意味着任何地形图块都可以像其他任何图块一样绘制为地形或单个图块。

“抛光”图块集通常具有变体,您应该在平台、地板等的角落或边缘使用这些变体。虽然可以手动放置这些,但这很快就会变得乏味。用程序生成的关卡处理这种情况也很困难,需要大量代码。

Godot 提供地形来自动执行这种瓦片连接。这允许您自动使用“正确”的瓷砖变体。

地形被分组为地形集。每个地形集都被分配了一种模式,来自 Match Corners and SidesMatch CornersMatch sides。它们定义地形集中的地形如何相互匹配。

笔记

以上模式对应于 Godot 3.x 中使用的先前位掩码模式 autotiles:2×2、3×3 或 3×3 最小。这也类似于Tiled编辑器的功能。

选择 TileMap 节点,转到检查器并在 TileSet资源中创建一个新地形集:

在 TileSet 资源检查器中创建地形集(在 TileMap 节点内)

创建地形集后,必须地形集中创建一个或多个地形:

在地形集中创建地形

在 TileSet 编辑器中,切换到选择模式并单击一个图块。在中间列中,展开Terrains部分,然后为图块指定一个地形集 ID 和一个地形 ID。表示“无地形设置”或“无地形”,这意味着您必须先将Terrain Set-1设置为或更大,然后才能将 Terrain设置为或更大。00

笔记

地形集 ID 和地形 ID 彼此独立。他们也是从0,而不是开始1

在 TileSet 编辑器的选择模式下在单个图块上配置地形

这样做之后,您现在可以配置在中间列中可见的Terrain Peering Bits部分。对等位确定将根据相邻图块放置哪个图块。-1是指空白空间的特殊值。

例如,如果一个图块的所有位都设置为0或更高,则只有当所有8 个相邻图块都使用具有相同地形 ID 的图块时,它才会出现。存在于角落或侧面。如果图块的位设置为0或更高,但左上角、顶部和右上角的位设置为-1,则它只会在其顶部有空白空间(包括对角线)时出现。

在 TileSet 编辑器的选择模式下配置单个瓦片上的地形对等位

完整图块表的示例配置如下所示:

横向卷轴游戏的完整图块表示例

带有可见地形对等位的横向卷轴游戏的完整图块表示例

一次将属性分配给多个图块

有两种方法可以一次将属性分配给多个图块。根据您的用例,一种方法可能比另一种更快:

使用多个图块选择

如果您希望一次配置多个属性,请选择TileSet 编辑器顶部的选择模式:

Shift执行此操作后,您可以通过按住然后单击图块来选择右列中的多个图块 。您也可以通过按住鼠标左键然后拖动鼠标来执行矩形选择。Shift最后,您可以通过按住然后单击选定的图块来取消选择已经选择的图块(不影响其余选择) 。

然后,您可以使用 TileSet 编辑器中间列中的检查器分配属性。只有您在此处更改的属性才会应用于所有选定的图块。就像在编辑器的检查器中一样,所选图块上不同的属性将保持不同,直到您对其进行编辑。

使用数字和颜色属性,您还将在编辑属性后在图集中的所有图块上看到属性值的预览:

使用选择模式选择多个图块,然后应用属性

使用瓷砖属性绘画

如果您希望一次将一个属性应用于多个图块,您可以为此使用属性绘制模式。

配置要在中间列中绘制的属性,然后单击右列中的图块(或按住鼠标左键)以将属性“绘制”到图块上。

使用 TileSet 编辑器绘制图块属性

Tile 属性绘制对于手动设置耗时的属性特别有用,例如碰撞形状:

绘制碰撞多边形,然后左键单击图块以应用它

创建替代图块

有时,您想要使用单个图块图像(在地图集中只找到一次),但以不同的方式配置。例如,您可能想要使用相同的图块图像,但旋转、翻转或使用不同的颜色进行调制。这可以使用替代瓷砖来完成。

要创建替代图块,请右键单击 TileSet 编辑器显示的地图集中的基础图块,然后选择创建替代图块

通过在 TileSet 编辑器中右键单击基础图块来创建替代图块

如果当前处于选择模式,则备选图块将已被选中进行编辑。如果当前不处于选择模式,您仍然可以创建替代图块,但您需要切换到选择模式并选择替代图块进行编辑。

如果您没有看到替代图块,请平移到图集图像的右侧,因为替代图块总是出现在 TileSet 编辑器中给定图集的基础图块的右侧:

在 TileSet 编辑器中单击后配置替代图块

选择替代图块后,您可以像在基本图块上一样使用中间列更改任何属性。但是,公开的属性列表与基础图块不同:

  • 替代 ID:此替代磁贴的唯一数字标识符。更改它会破坏现有的 TileMap,所以要小心!此 ID 还控制在编辑器中显示的替代图块列表中的排序。

  • Rendering > Flip H:如果true,瓦片被水平翻转。

  • Rendering > Flip V:如果true,瓦片被垂直翻转。

  • Rendering > Transpose:如果true,tile 逆时针旋转 90 度。将其与Flip H和/或Flip V结合使用以执行 180 度或 270 度旋转。

  • 渲染 > 纹理原点:用于绘制图块的原点。与基础图块相比,这可用于在视觉上偏移图块。

  • 渲染 > 调制:渲染图块时要使用的颜色倍增器。

  • Rendering > Material:要用于该图块的材料。这可用于将不同的混合模式或自定义着色器应用于单个图块。

  • Z 索引:此图块的排序顺序。较高的值将使瓦片渲染在同一层上的其他瓦片前面。

  • Y 排序原点:用于基于其 Y 坐标(以像素为单位)的图块排序的垂直偏移。这允许使用图层,就好像它们在自上而下游戏的不同高度上一样。调整此项有助于缓解对某些图块进行排序的问题。仅当Y Sort EnabledtrueTileMap 层上放置瓦片时才有效。

您可以通过单击替代图块旁边的大“+”图标来创建其他替代图块变体。这相当于选择基本图块并右键单击它以再次选择“创建替代图块”

笔记

创建替代图块时,不会继承基础图块的任何属性。如果您希望基础磁贴和替代磁贴上的属性相同,则必须在替代磁贴上再次设置属性。

使用 TileMaps

也可以看看

此页面假定您已经创建或下载了 TileSet。如果没有,请先阅读使用 TileSet,因为您将需要一个 TileSet 来创建 TileMap。

介绍

瓦片地图是用于创建游戏布局的瓦片网格。使用TileMap节点设计关卡有几个好处。首先,它们可以通过将图块“绘制”到网格上来绘制布局,这比 一个接一个地放置单个Sprite2D节点要快得多。其次,它们允许更大的级别,因为它们针对绘制大量图块进行了优化。最后,您可以向图块添加碰撞、遮挡和导航形状,从而为 TileMap 添加更强大的功能。

笔记

Godot 4.0 已将几个 per-tile 属性(例如 tile rotation)从 TileMap 移动到 TileSet。在 TileMap 编辑器中无法再旋转单个图块。相反,必须使用 TileSet 编辑器来创建替代的旋转图块。

此更改可实现更大的设计一致性,因为并非每个图块都需要在 TileSet 中旋转或翻转。

在 TileMap 中指定 TileSet

如果您已按照使用 TileSets上的上一页进行操作,则应该有一个内置到 TileMap 节点的 TileSet 资源。这有利于原型制作,但在现实世界的项目中,您通常会有多个关卡重用同一个图块集。

在多个 TileMap 节点中重用同一个 TileSet 的推荐方法是将 TileSet 保存到外部资源。为此,请单击 TileSet 资源旁边的下拉菜单并选择保存

将内置的 TileSet 资源保存到外部资源文件

创建 TileMap 图层

从 Godot 4.0 开始,您可以在单个 TileMap 节点中放置多个图层。例如,这允许您区分前景图块和背景图块,以便更好地组织。您可以在给定位置每层放置一个瓷砖,如果您有多于一层,则可以将多个瓷砖重叠在一起。

默认情况下,一个 TileMap 节点自动有一个预制层。如果您只需要一个图层,则不必创建其他图层,但如果您现在想这样做,请选择 TileMap 节点并在检查器中展开图层部分:

在 TileMap 节点中创建图层(带有“背景”和“前景”的示例)

每个层都有几个可以调整的属性:

  • 名称:显示在 TileMap 编辑器中的人类可读名称。这可以是“背景”、“建筑物”、“植被”等。

  • Enabled:如果true,图层在编辑器中和运行项目时可见。

  • 调制:用作层上所有图块的倍增器的颜色。这也乘以每个图块的Modulate属性和 TileMap 节点的Modulate属性。例如,您可以使用它来使背景图块变暗以使前景图块更加突出。

  • Y Sort Enabled:如果true,则根据 TileMap 上的 Y 位置对图块进行排序。这可用于防止某些图块设置的排序问题,尤其是等距图块。

  • Y 排序原点:用于对每个图块进行 Y 排序的垂直偏移量(以像素为单位)。仅当Y Sort Enabled为 时才有效true

  • Z Index:控制该图层是绘制在其他 TileMap 图层的前面还是后面。这个值可以是正的也可以是负的;Z 索引最高的图层绘制在其他图层之上。如果多个图层具有相同的 Z 索引属性,图层列表中的最后一个图层(出现在列表底部的图层)将绘制在顶部。

您可以通过拖放“图层”部分条目左侧的“三个水平条”图标来重新排序图层。

笔记

您可以在未来创建、重命名或重新排序图层,而不会影响现有的图块。不过要小心,因为移除图层也会移除放置在该图层上的所有图块。

打开 TileMap 编辑器

选择 TileMap 节点,然后打开编辑器底部的 TileMap 面板:

打开编辑器底部的 TileMap 面板。必须首先选择 TileMap 节点。

选择用于绘画的瓷砖

首先,如果您在上面创建了其他图层,请确保您已选择要在其上绘画的图层:

在 TileMap 编辑器中选择要绘制的图层

提示

在 2D 编辑器中,您当前未从同一 TileMap 节点编辑的层将在 TileMap 编辑器中显示为灰色。您可以通过单击图层选择菜单旁边的图标来禁用此行为(突出显示选定的 TileMap 图层工具提示)。

如果您还没有创建其他层,则可以跳过上述步骤,因为进入 TileMap 编辑器时会自动选择第一层。

在 2D 编辑器中放置图块之前,您必须在位于编辑器底部的 TileMap 面板中选择一个或多个图块。为此,请在 TileMap 面板中单击一个图块,或按住鼠标按钮选择多个图块:

通过单击在 TileMap 编辑器中选择一个图块

提示

与在 2D 和 TileSet 编辑器中一样,您可以使用鼠标中键或右键在 TileMap 面板上平移,并使用鼠标滚轮或左上角的按钮进行缩放。

您也可以按住Shift以追加到当前选择。选择多块时,每次执行绘画操作时都会放置多块块。这可用于在一次单击中绘制由多个图块组成的结构(例如大型平台或树木)。

最终选择不必是连续的:如果所选图块之间有空白,则在 2D 编辑器中绘制的图案中将留空。

通过按住鼠标左键在 TileMap 编辑器中选择多个图块

如果您在 TileSet 中创建了替代图块,则可以选择它们在基础图块的右侧进行绘制:

在 TileMap 编辑器中选择替代图块

最后,如果您在 TileSet 中创建了场景集合,则可以将场景图块放置在 TileMap 中:

使用 TileMap 编辑器放置包含粒子的场景图块

绘画模式和工具

使用 TileMap 编辑器顶部的工具栏,您可以在多种绘画模式和工具之间进行选择。这些模式会影响在 2D 编辑器中单击时的操作,而不是TileMap 面板本身。

从左到右,您可以选择的绘画模式和工具是:

选择

通过单击单个图块选择图块,或按住鼠标左键在 2D 编辑器中使用矩形选择多个图块。请注意,不能选择空白区域:如果您创建矩形选区,则只会选择非空的图块。

要附加到当前选择,请按住Shift然后选择一个图块。要从当前选择中移除,请按住Ctrl然后选择一个图块。

然后可以在任何其他绘画模式中使用该选择来快速创建已放置图案的副本。

在选择模式下,您不能放置新的瓷砖,但您仍然可以在做出选择后通过右键单击来擦除瓷砖。无论您在选区中单击什么位置,整个选区都将被删除。

在绘画模式下,您可以通过按住Ctrl 然后执行选择来暂时切换此模式。

提示

您可以复制和粘贴已放置的图块,方法是执行选择,然后按。左键单击后将粘贴选择。您可以再按 一次以这种方式执行更多副本。右键单击或按取消粘贴。Ctrl + CCtrl + VCtrl + VEscape

标准的绘画模式允许您通过单击或按住鼠标左键来放置图块。

如果右击,当前选择的图块将从图块地图中删除。换句话说,它将被空白空间取代。

如果您在 TileMap 中选择了多个图块或使用选择工具,则每次您在按住鼠标左键的同时单击或拖动鼠标时,它们都会被放置。

提示

在画图模式下,您可以在按住鼠标左键Shift 之前按住 ,然后将鼠标拖动到线条的终点来绘制线条。这与使用下面描述的直线工具相同。

Ctrl您也可以通过在按住和Shift 之前按住鼠标左键,然后将鼠标拖动到矩形的端点来绘制矩形。这与使用下面描述的矩形工具相同。

Ctrl 最后,您可以通过按住然后单击一个图块(或按住并拖动鼠标)来在 2D 编辑器中拾取现有图块。这会将当前绘制的图块切换为您刚刚单击的图块。这与使用下面描述的选择器工具相同。

线

选择线条绘制模式后,您可以绘制一条始终为 1 个图块粗的线条(无论其方向如何)。

如果您在线条绘画模式下右键单击,您将擦除一行。

如果您在 TileMap 中或使用选择工具选择了多个图块,则可以将它们放置在一条线上的重复图案中。

在绘画或橡皮擦模式下,您可以通过按住 Shift然后绘图来暂时切换此模式。

选择两个瓷砖后使用线条工具对角绘制平台

长方形

选择矩形绘制模式后,您可以绘制一个轴对齐的矩形。

如果在“矩形绘画”模式下右键单击,您将擦除轴对齐的矩形。

如果您在 TileMap 中或使用选择工具选择了多个图块,则可以将它们放置在矩形内的重复图案中。

在“绘画”或“橡皮擦”模式下,您可以通过按住 Ctrl然后Shift绘图来暂时切换此模式。

桶装满

选择 Bucket Fill 模式后,您可以通过切换出现在工具栏右侧的Contiguous复选框来选择绘画是否应仅限于连续区域。

如果启用“连续”(默认),则只会替换与当前选择相接触的匹配图块。这种连续检查是水平和垂直执行的,但不是对角线的。

如果禁用Contiguous,则整个 TileMap 中具有相同 ID 的所有瓦片都将被当前选中的瓦片替换。如果选择未选中Contiguous的空瓦片 ,则包含 TileMap 有效区域的矩形中的所有瓦片都将被替换。

如果在 Bucket Fill 模式下右键单击,您将用空瓷砖替换匹配的瓷砖。

如果您在 TileMap 中或使用选择工具选择了多个图块,则可以将它们放置在填充区域内的重复图案中。

使用桶填充工具

选择器

选择拾取器模式后,您可以通过按住然后单击一个图块来在 2D 编辑器中拾取现有图块Ctrl。这会将当前绘制的图块切换为您刚刚单击的图块。您也可以通过按住鼠标左键并形成一个矩形选区来一次拾取多个图块。只能挑选非空的瓷砖。

在绘画模式下,您可以通过按住Ctrl 然后单击或拖动鼠标来暂时切换此模式。

橡皮

此模式与任何其他绘画模式(Paint、Line、Rectangle、Bucket Fill)相结合。启用橡皮擦模式后,单击鼠标左键时,图块将被空图块替换,而不是绘制新线。

您可以在任何其他模式下通过右键单击而不是左键单击来临时切换此模式。

使用散射随机绘画

绘画时,您可以选择启用随机化。启用后,绘画时将在所有当前选定的图块之间随机选择一个图块。这是由绘画、线条、矩形和桶填充工具支持的。为了有效地随机绘制,您必须在 TileMap 编辑器中选择多个图块或使用散射(这两种方法可以结合使用)。

如果Scattering设置为大于 0 的值,则在绘制时有可能不会放置任何图块。这可用于向大区域添加偶尔的、非重复的细节(例如在大型自上而下的 TileMap 上添加草或面包屑)。

使用绘画模式时的示例:

多次选择随机选择,然后按住鼠标左键作画

使用 Bucket Fill 模式时的示例:

对单个图块使用桶填充工具,但启用了随机化和散射

笔记

橡皮擦模式不考虑随机化和散射。选择中的所有图块始终被删除。

使用模式保存和加载预制瓷砖放置

虽然您可以在选择模式下复制和粘贴图块,但您可能希望保存图块的预制图案以便随时放置在一起。这可以通过选择TileMap 编辑器的Patterns选项卡在每个 TileMap 的基础上完成。

要创建新图案,请切换到选择模式,进行选择并按下 。单击“图案”选项卡中的空白区域(空白区域周围应出现一个蓝色焦点矩形),然后按:Ctrl + CCtrl + V

从 TileMap 编辑器中的选择创建新模式

要使用现有图案,请在“图案”选项卡中单击其图像,切换到任何绘画模式,然后左键单击 2D 编辑器中的某处:

使用 TileMap 编辑器放置现有模式

与多图块选择一样,如果与线条、矩形或桶填充绘画模式一起使用,图案将被重复。

笔记

尽管在 TileMap 编辑器中进行了编辑,但模式仍存储在 TileSet 资源中。这允许在加载保存到外部文件的 TileSet 资源后在不同的 TileMap 节点中重用模式。

使用地形自动处理瓦片连接

要使用地形,TileMap 节点必须具有至少一个地形集和该地形集中的一个地形。如果您还没有为 TileSet 创建地形集,请参阅 创建地形集(自动拼接) 。

地形连接有3种绘制模式:

  • Connect,其中瓦片连接到同一 TileMap 层上的周围瓦片。

  • Path,其中瓦片连接到以同一笔画绘制的瓦片(直到松开鼠标按钮)。

  • 特定于图块的覆盖以解决冲突或处理地形系统未涵盖的情况。

连接模式更易于使用,但路径更灵活,因为它允许艺术家在绘画过程中进行更多控制。例如,Path 可以允许道路彼此直接相邻而不相互连接,而 Connect 将强制两条道路连接。

在 TileMap 编辑器的地形选项卡中选择连接模式

在 TileMap 编辑器的地形选项卡中选择路径模式

最后,您可以从地形中选择特定的图块来解决某些情况下的冲突:

在 TileMap 编辑器的 Terrains 选项卡中使用特定的图块进行绘制

至少有一个位设置为相应地形 ID 的值的任何图块将出现在图块列表中以供选择。

处理丢失的瓷砖

如果您删除 TileMap 中引用的 TileSet 中的图块,TileMap 将显示一个占位符以指示放置了无效的图块 ID:

由于 TileSet 引用被破坏,TileMap 编辑器中缺少图块

这些占位符在正在运行的项目中是可见的,但切片数据仍然保存在磁盘中。这使您可以安全地关闭和重新打开此类场景。一旦您重新添加具有匹配 ID 的图块,这些图块将以新图块的外观出现。

笔记

在您选择 TileMap 节点并打开 TileMap 编辑器之前,缺失的图块占位符可能不可见。

猜你喜欢

转载自blog.csdn.net/drgraph/article/details/130815479