I have a question - how do I get and set the position of object in Godot? I couldn't find any tutorials, so I need help.
So we have three kinds of Node
s by their positioning rules: Control
, Node2D
, and Spatial
. Since you mention 3D, I'll talk about Spatial
on this answer.
You can find the differences between Node2D
and Control
on Why do some nodes use "position" and others use "rect_position"?. I also talk a little bit about Spatial
there.
Spatial
The way Spatial
are placed is by their Transform
. This is similar to how Node2D
are placed by their Transform2D
.
You might expect Spatial
to have a "position" property, the way Node2D
has one. However they don't. Instead they have a translation
property. So you would get or set that instead, for example:
translation = Vector3(1.0, 2.0, 3.0)
However, there is no "global_translation". I'll get to how to workaround that.
Godot 4 Note: In Godot 4 Spatial
has been renamed to Node3D
, and they do have position
instead of translation
. Although no "global_position".
I was saying that Spatial
nodes are placed by their Transform
. A Transform
has two parts:
Basis
called basis
. Which you can conceptualize as a set of three Vector3
that defines the axis of the coordinate system of the Spatial
, or as a 3 by 3 matrix.Vector3
called origin
. Which you can conceptualize as the origin position (aha!) of the coordinate system of the Spatial
, or as vector that augments the 3 by 3 matrix to add a translation to the transformation.Thus, you can place Spatial
nodes by setting the origin
of their Transform
(which is equivalent to setting translation
). For example:
transform.orign = Vector3(1.0, 2.0, 3.0)
It is worth noting that a Spatial
has a transform
property which is relative to their parent, and a global_transform
which we will say it is relative to the world. If you compose (multiply, as in "matrix multiplication") all the transform
from the root of the scene tree to your Spatial
, you would have computed its global_transform
.
You can directly get or set the origin
of the global_transform
. For example:
global_transform.orign = Vector3(1.0, 2.0, 3.0)
And this would be the equivalent to the missing "global_translation"/"global_position".
RigidBody
I also want to point out that directly modifying the transform of a RigidBody
might be undesirable. To be more precise, the physics engine that Godot is using might want to move the RigidBody
, and then you end up fighting the physics engine.
With that said. If you need to teleport a RigidBody
, you can request it to the physics engine, like this:
PhysicsServer.body_set_state(
get_rid(),
PhysicsServer.BODY_STATE_TRANSFORM,
Transform.IDENTITY.translated(Vector3(1.0, 2.0, 3.0))
)
Yes, this works regardless of its mode
. In fact, in my experience, this approach is better than switching modes.