这是什么技术原因?它对我来说似乎很奇怪,为什么它们不能都只使用position呢?这是遗留问题吗?
有三组相关的节点:那些扩展:
Control
,在这里您会找到rect_position
。Node2D
,在这里您会找到position
。Spatial
,在这里您只会找到transform
。这些节点有不同的颜色编码。所有的Control
是绿色的,所有的Node2D
是蓝色的,而所有的Spatial
是红色的。是的,这对于颜色视觉缺陷是一个可访问性问题。这里提出了一个重新设计图标的呼吁:调整编辑器节点图标使其不依赖颜色以区别(适合色盲者)。
是的,有一些命名上的混乱。首先,2D节点在名称中说“2D”,但3D节点不说(例如Camera
与Camera2D
)。特别是在Godot 4.0中已经发生了变化。
如果您有关于命名如何更好的想法,可以提出提案(作为github上的问题)。
让我们来谈谈这些节点集的定位方式的不同之处...
关于变换
Spatial
节点使用Transform
。事实上,有些人已经建议将transform
属性重命名为“position”。正如您所知道的,这并不是同一件事,因为Transform
不仅包括位置,而且还包括旋转、缩放等等。
我知道您没有询问transform
。然而,您需要知道的是,Node2D
也有一个Transform2D
类型的transform
属性。这就是Node2D
的实际定位方式。而position
、rotation
、rotation_degrees
和scale
则是为了方便使用。
控件定位
Spatial
和Node2D
都有transform
。猜猜?Control
没有。相反,Control
被设计成用以下任一方式定位:
anchor_*
)和边距(margin_*
)设置。抽象地说,锚点是因子,而边距是偏移量。例如,控件的最左侧部分将位于anchor_left * parent_width + margin_left
处。rect_position
和rect_size
设置。其中rect_position
是相对于父级左上角的位置。需要注意的一点是:保持了rect_min_size
。是的,还有rect_rotation
和rect_scale
,它们可能会对上述解释造成影响,但它们的使用方式与人们想象的一样。
我说“打算”是因为可以混合使用这些方法。例如,您可以通过锚点和边距来定位控件,或者将其放置在容器中,但然后使用rect_position
进行动画效果。
如您所见,position
和rect_position
是两个不同的东西。并不是某些节点被卡在一个名称或其他类似的名称上。
我还应该提到,这些属性都有“全局”版本,因为它们相对于其父级定位。
关于前缀
好吧,它们不同,但就第一近似而言,它们做着相同的事情。为什么它们不能有相同的名称?
除了提醒它们不是同一个东西之外,Godot中给属性添加前缀还有一个原因:便于在检查器面板中将它们分组。
例如,“锚点”组将包含所有属性名以anchor
开头的属性,而该前缀不会显示在属性名称上。
同样,您可以在找到的组中找到“矩形”组。是的,rect_position
就在其中。此外还有相关属性。这也有助于从代码编辑器中发现这些属性,因为它们会在自动完成时一起显示。
所有这些都应该使新用户更容易理解控件定位的工作原理。然而,让我们诚实地说,它的效果并不好。请参阅提案:重新设计向用户呈现用户界面(控件)缩放的方式。
Node2D中的控件
您可以将Control
放置在Node2D
中,有时您可能需要这样做。例如,如果您希望一个Label
或ProgressBar
(它们是Control
)跟随在Node2D
后面,Godot会处理其位置。但是,您会发现缩放和居中存在问题,因为Node2D
没有Control
可以使用的大小(一些如Sprite
具有视觉大小作为其Texture
的属性,但这不会公开为属性,而且Control
不使用它)。
这就是您可能想要使用一些混合了rect_position
和position
代码来解决问题的地方。
将Control
居中于Node2D
本身并不困难(有容器、锚点和边距以及手动定位方法)。问题是当其尺寸变化时保持其居中状态,特别是当您向Label
添加更多文本时,其尺寸会不断增加。但是请不要担心,您需要处理resized
信号,并在其中调用set_anchors_and_margins_preset
,这就是您从编辑器的"布局"选项中所做的。
在控件内放置Node2D
您也可以将Node2D
放置在Control
内部,此时Godot也会处理其位置。您可能需要在Control
上设置rect_clip_content
。
但是,在Container
中放置Node2D
无法正常工作。 Container
无法处理Node2D
子元素。
如果您正在尝试这样做,可能需要执行以下操作之一:
Sprite
(一个Node2D
)更改为TextureRect
(一个Control
)。TouchScreenButton
(一个Node2D
)更改为Button
(一个Control
),并在项目设置->输入设备->指针中启用触摸模拟。Camera2D
的Viewport
与您想要在其中显示的任何Node2D
。 我建议将其作为单独场景进行设计以便于设计。不要忘记给Viewport
大小。然后,要么:
Viewport
放入ViewportContainer
(一个Control
)中。您可能需要将ViewportContainer
的stretch
设置为true。ViewportTexture
的TextureRect
。顺便说一句,建议将主场景的根节点设置为Node
(不是任何派生类型),然后使用CanvasLayer
来分离UI和游戏世界。这将防止Camera2D
影响UI。