Lesson 03
Now we build the player as a proper physics character — a capsule that walks on the ground, respects gravity, and moves relative to input. This is the CharacterBody3D pattern you'll reuse in every 3D project.
Player. Save as player.tscn.CharacterBody3D
The go-to node for player-controlled characters. Unlike a RigidBody, you drive it — you set velocity and call move_and_slide(), and it handles collision response (sliding along walls, stopping at floors). Predictable and easy to tune.
Attach a script player.gd to the root Player node:
extends CharacterBody3D
const SPEED: float = 6.0
const GRAVITY: float = 20.0
func _physics_process(delta: float) -> void:
# Apply gravity when airborne.
if not is_on_floor():
velocity.y -= GRAVITY * delta
# Read movement input as a 2D vector (x = strafe, y = forward/back).
var input_dir: Vector2 = Input.get_vector(
"move_left", "move_right", "move_forward", "move_back")
# Convert to a 3D direction on the XZ plane.
# input_dir.y maps to -Z because forward is -Z.
var direction: Vector3 = Vector3(input_dir.x, 0, input_dir.y)
direction = direction.normalized()
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
move_and_slide()_physics_process, not _process
Physics and movement go in _physics_process(delta), which runs at a fixed rate. Using _process for physics gives inconsistent movement on different framerates. Rule of thumb: anything touching velocity or move_and_slide() goes in _physics_process.
move_forward (W/Up), move_back (S/Down), move_left (A/Left), move_right (D/Right), and jump (Space).Input.get_vector
Input.get_vector(left, right, up, down) returns a Vector2 already normalized for diagonals, so moving diagonally isn't faster than moving straight — a subtle bug you'd otherwise have to fix by hand.
Extend player.gd with a jump before the move_and_slide() call:
const JUMP_VELOCITY: float = 8.0
# ...inside _physics_process, after gravity, before move_and_slide():
if is_on_floor() and Input.is_action_just_pressed("jump"):
velocity.y = JUMP_VELOCITYmain.tscn. Drag player.tscn from the FileSystem dock into the scene tree under Main (or Instance Child Scene).Falling forever
If the player falls through the floor, your ground is missing its CollisionShape3D, or the player's collision capsule is misaligned. Both bodies need collision shapes that actually overlap.
Checkpoint — expected state
player.tscn CharacterBody3D with mesh and collision capsule._physics_process.