Search code examples
positiongodotgdscript

How to set and get position of an Object in Godot (3D)


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.


Solution

  • So we have three kinds of Nodes 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:

    • A 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.
    • A 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.