Godot Engine – Movement and Rotation basics

Godot engine is a 2d and 3d open source cross platform game engine. The beauty of it is not only can export to most of the platforms but also the editor can run on Windows, Mac and Linux. As of now, Godot engine is 2.0 beta and you can download it from the official website godotengine.org.

This post is targeted towards beginners who are coming to Godot engine from other engines. If you have no experience in any game development, you may get some help here but I recommend you to look at Godot wiki on vector maths and transformations. I believe you can apply these in advanced things like character movement, camera control etc.

Vector
A vector represents a magnitude and direction. In a game engine, a vector is used to represent a position or a direction.

3d world

Red is x axis, yellow is y and blue is z
Red is x axis, yellow is y and blue is z

Let us assume that there is a 3d world in Godot. The world is where we put all game objects and it is where the game runs.

If we add the global right vector i.e, Vector3(1,0,0) to a game object which is at the world origin(0,0,0), the object’s new position will be Vector3(1,0,0) irrespective of its rotation. It just moves on the world x axis, that’s all.

If you are coming from Unity, take note that Godot has a slight difference in the axes compared to Unity. The forward direction is not positive z, but it is negative z. So when we export from blender, make sure the forward is -z forward and y is up.

Forward is inverse z
Forward is inverse z

Every object in the game world also has its own position and a direction. This position and direction is stored as a Matrix. You only need to understand that every object has a transformation matrix which represents the position and its orientation(also the scale, but leave it for now). We can get this Matrix by calling get_transform() on an object. There is also a get_global_transform() method which returns the transformation with respect to the game world.
So if we know the transform of a game object, we can get its position and its direction. We get the position from its origin and orientation from its basis.

Also Read:   Using HTTPClient in Godot

Enough talk on vectors and matrices, let us jump into action

Moving in global axes
This code moves the object on the world x axis.

func _process(delta):
    t = get_transform()
    t.origin += Vector3(delta,0,0)
    set_transform(t)

By changing the origin of the transform, we can change the position of the object. Instead of using this code, godot provides a simpler method for doing this.

func _process(delta):
    global_translate(Vector3(delta,0,0))

The above code just moves the gameobject on the world x axis.
movement in global directionEven if we rotate the object, it just moves along the world x axis because the object is moved in global x axis. Global transform is independent of local position and rotation.
movement in global direction

Moving in local axes
If we want to move the object to its right side, the above code won’t work. For that we need to know the local right direction vector of the object. We can do this by,

t = get_transform()
t.origin += t.basis.x * delta
set_transform(t)

We take the right directional vector which is the transform basis.x of the object and add it to the position. Godot engine has easy and simple methods for doing this.

translate(Vector3(delta,0,0))

Here we are asking to move on its own local axes by using translate instead of global_translate. The passed Vector3(delta,0,0) is converted to its local space internally. If we want to move to the forward direction, which is -z,

translate(Vector3(0,0,-delta))

Move to a position
To move to a position, we need to get the direction vector from the object to the target position. We have a targetObject which is where we want the object to go. So, we find the direction vector by subtracting the source from the destination position. We only need the normalized vector which just represents the direction.

var dir = (get_node(targetObject).get_global_transform().origin - get_global_transform().origin).normalized()
global_translate(dir*delta)

If we want to change the speed we just multiply the delta with the speed like dir*speed*delta.

Also Read:   Godot Engine game tutorial for beginners - Create a 2D racing game part 5

Rotation of an object
Rotation is somewhat complex if we dig deep. In the editor, the rotation is represented in euler angles. It is super simple that each of the three angles represent the rotation in all angles. In 3d, multiple different euler angle rotations causes the axis rotations to appear locked. This is called Gimbal Lock. To avoid that, 3d rotations are done using Quaternions. Quaternions are used to represent the orientation of a 3d object.

If we are not going to change an object’s rotation dynamically or only rotating a single axis, then use euler angles. We can rotate an object in euler angles by rotate_x, rotate_y, rotate_z methods.

Looking at an object
Godot already has a built-in look_at method to which we can pass the target object position and the object will look to that position.

var lookPos = get_node(lookTarget).get_transform().origin
look_at(lookPos,Vector3(0,1,0))

Quaternion look at

var t = get_transform()
var lookDir = get_node(lookTarget).get_transform().origin - t.origin
var rotTransform = t.looking_at(get_transform().origin+lookDir,Vector3(0,1,0))
var thisRotation = Quat(rotTransform.basis)
set_transform(Transform(thisRotation,t.origin))

Linear Interpolation (lerp)
Lerping can calculate the value at any point between two known values. You can search more on the entire internet about linear interpolation. Let us look at an example, if we have two numbers 100 and 200, lerp at 0.5 and we get the middle of 100 and 200, which is 150. The lerp amount can vary from 0 to 1 to get the minimum and the maximum original values. In the above example 0 is 100 and 1 is 200.
Using this logic, we can lerp between two vectors to move an object just by changing the lerp amount.

var value = 0;
func _process(delta):
    t = get_transform()
    
    var start = Vector3(0,0,0)
    var end = get_node(targetObject).get_transform().origin
    var pos = start.linear_interpolate(end,value)
    value += delta

    t.origin = pos
    set_transform(t)

lerp_basic

We can see that the object moves from the origin to the targetObject position. It won’t stop because lerping is not limited to 0 and 1, we can just pass any number, 0 and 1 represents minimum and maximum values.

Also Read:   Create a Catch The Egg game in Godot engine - 4

Smoothed Arrival using Lerp
We can smooth the movement of an object while reaching its target by lerping.

t = get_transform()
var end = get_node(lookTarget).get_transform().origin
t.origin = t.origin.linear_interpolate(end,delta)
value += delta
if value>1:
value = 1
set_transform(t)

lerp_smooth_arrival

Godot engine has methods for lerping between float values, Vectors and Colors.

Spherical Linear Interpolation (slerp)
Slerping is mostly used when interpolating between quaternions. This can be used to make a behaviour for a turret or something like that which rotates gradually in time.

var lookDir = get_node(lookTarget).get_transform().origin - t.origin
var rotTransform = t.looking_at(lookDir,Vector3(0,1,0))
var thisRotation = Quat(t.basis).slerp(rotTransform.basis,value)
value += delta
if value>1:
    value = 1
set_transform(Transform(thisRotation,t.origin))

slerp

Do you know how to rotate an object to its moving direction? Just create a lastPos variable which stores the last position of the object. Then in the above code, get the lookDir like this,

var lookDir = t.origin - lastPos
lastPos = t.origin

That’s all for now and hope you learned something from this. In the following posts we will build up from this and do something creative. Thanks for reading.

[Total: 17    Average: 3.9/5]