What's the technical reason for this? It seems strange to me that they can't all just use position. Is it a legacy thing?
There are three relevant sets of nodes. Those that extend:
Control
, it is here where you findrect_position
.Node2D
, it is here where you findposition
.Spatial
, and here you only findtransform
.
These nodes are color coded. All Control
s are green, all Node2D
are blue, and all Spatial
s are red. And yes, that is an accessibility concern regarding color vision deficiency. There is a call for an icon redesign here: Tweak editor node icons to be distinguishable without relying on color (colorblind-friendly).
And yes, there is some naming mess. For starter 2D nodes say "2D" in the name, but 3D nodes don't (e.g. Camera
vs Camera2D
). That in particular has changed for Godot 4.0.
If you have ideas of how the naming can be better, you may open a proposal (as an issue on github).
Let us talk about how the positioning of these sets of nodes differ…
On Transforms
Spatial
nodes use Transform
. In fact, some people has proposed renaming the transform
property to "position". Which, as you would know, is not the same thing, because a Transform
not only has position but also rotation, scaling, and such.
I know you didn't ask about transform
. However, you need to know that a Node2D
also has a transform
property, of type - you gusseted - Transform2D
. And this is how a Node2D
is actually positioned. Meanwhile position
, rotation
, rotation_degrees
and scale
are for ease of use.
Positioning Controls
Spatial
and Node2D
have transform
. Guess what? Control
does not. Instead a Control
is intended to be positioned in one of these ways:
- It is placed in a
Container
(Which are alsoControl
s), and theContainer
decides how it is positioned, taking into account "Size Flags" (that is what they are for). - By anchors (
anchor_*
) and margins (margin_*
). The abstract is that the anchors are factors, and the margins are offset. For example, the leftmost part of the control will be positioned atanchor_left * parent_width + margin_left
. - By
rect_position
andrect_size
. Whererect_position
is position from the top left corner of parent.
One caveat: rect_min_size
is uphold. And yes, there is also rect_rotation
and rect_scale
which throw a wrench on the above explanation, but it works as one would imagine.
And I say intended because you can mix these. For example, you can position a control by anchors and margins, or by placing it in a Container
, but then animate the rect_position
for effect.
As you can see, position
and rect_position
are two different things. It is not the case that some nodes got stuck with one name or the other or something like that.
I should also mention that there are "global" version of these properties, because they are positioned respect to their parent.
On the prefix
Ok, they are different, but they do - to a first approximation - the same thing. Why can't they have the same name?
Beyond it being a reminder that they aren't the same thing. There is a reason to prefix properties in Godot. And that is to ease grouping them in the inspector panel.
For example, the "Anchor" group will have all the properties which name begin with anchor
, and that prefix is not shown on the name of the property.
Similarly, one of the groups you find is "Rect". And yes, rect_position
is inside. Along side related properties. This also helps in discovering these properties from the code editors, since they would show up together in autocomplete.
This all should make it easier for new user to figure out how Control
positioning works. However, let us be honest, it is not working great. See also the proposal: Redesign how user interface (Controls) scaling is presented to the user.
Controls inside Node2D
You can - and you may need to - place Control
s inside of a Node2D
. For example, if you want a Label
or a ProgressBar
(which are Control
) following a Node2D
.
Godot will handle the position. But you will find problems with scaling and centering, because Node2D
don't have a size that the Control
s can use (some - such as Sprite
- have a visual size as virtue of their Texture
, which is not exposed as a property, and Control
does not use it).
It is there where may want to hack it with some code that mixes rect_position
and position
.
Centering a Control
in a Node2D
is not hard per se (there are Containers
, anchors and margins, and good old hand positioning). The problem is keeping it centered when the it changes size. In particular when you add more text to a Label
, which insist in growing to the right despite all odds. But do not fret, what you need is to handle the resized
signal and there call set_anchors_and_margins_preset
, which is what you do from the "Layout" option in the editor.
Node2D inside Controls
You may also place a Node2D
inside a Control
, and again Godot will handle the position. You may want to set rect_clip_content
on the Control
.
However, placing a Node2D
inside a Container
does not work properly. The Container
cannot handle Node2D
children.
If you are trying to do that, chances are that you need to do one of these:
- Change a
Sprite
(aNode2D
) to aTextureRect
(aControl
). - Change a
TouchScreenButton
(aNode2D
) to aButton
(aControl
) and enable touch emulation in Project Settings -> Input Devices -> Pointing. - Have a
Viewport
with aCamera2D
along side whateverNode2D
you want to display there. Which I recommend to make as a separate scene for ease of design. Don't forget to give size to theViewport
. And then, either:- Place that
Viewport
inside of aViewportContainer
(aControl
). You may want to set thestretch
of theViewportContainer
to true. - Or use a
TextureRect
with aViewportTexture
.
- Place that
While I'm at it, I'll also suggest to make the root of your main scene a Node
(not any derived type), and then use CanvasLayer
s to separate the UI from the game world. That will prevent the Camera2D
from affecting the UI.
© 2022 - 2024 — McMap. All rights reserved.