Moving the player with codeΒΆ

It's time to code! We're going to use the input actions we created in the last part to move the character.

Right-click the Player node and select Attach Script to add a new script to it. In the popup, set the Template to Empty before pressing the Create button.


Let's start with the class's properties. We're going to define a movement speed, a fall acceleration representing gravity, and a velocity we'll use to move the character.

extends CharacterBody3D

# How fast the player moves in meters per second.
@export var speed = 14
# The downward acceleration when in the air, in meters per second squared.
@export var fall_acceleration = 75

var target_velocity = Vector3.ZERO

These are common properties for a moving body. The target_velocity is a 3D vector combining a speed with a direction. Here, we define it as a property because we want to update and reuse its value across frames.


The values are quite different from 2D code because distances are in meters. While in 2D, a thousand units (pixels) may only correspond to half of your screen's width, in 3D, it's a kilometer.

Let's code the movement. We start by calculating the input direction vector using the global Input object, in _physics_process().

func _physics_process(delta):
    # We create a local variable to store the input direction.
    var direction = Vector3.ZERO

    # We check for each move input and update the direction accordingly.
    if Input.is_action_pressed("move_right"):
        direction.x += 1
    if Input.is_action_pressed("move_left"):
        direction.x -= 1
    if Input.is_action_pressed("move_back"):
        # Notice how we are working with the vector's x and z axes.
        # In 3D, the XZ plane is the ground plane.
        direction.z += 1
    if Input.is_action_pressed("move_forward"):
        direction.z -= 1

Here, we're going to make all calculations using the _physics_process() virtual function. Like _process(), it allows you to update the node every frame, but it's designed specifically for physics-related code like moving a kinematic or rigid body.

See also

To learn more about the difference between _process() and _physics_process(), see Idle and Physics Processing.

We start by initializing a direction variable to Vector3.ZERO. Then, we check if the player is pressing one or more of the move_* inputs and update the vector's x and z components accordingly. These correspond to the ground plane's axes.

These four conditions give us eight possibilities and eight possible directions.

In case the player presses, say, both W and D simultaneously, the vector will have a length of about 1.4. But if they press a single key, it will have a length of 1. We want the vector's length to be consistent, and not move faster diagonally. To do so, we can call its normalize() method.

#func _physics_process(delta):