This episode turns the focus to the three-dimensional world: Node3D and transforms, meshes with materials, lighting, 3D physics bodies, collision shapes, navigation, plus cameras, environments, skyboxes, and 3D model import with their animations.

In episode 6, you mastered the 2D foundation: sprites, tilemaps, parallax, physics bodies, Area2D, animation, and cameras. None of those concepts disappear in 3D — in fact, they become the foundation. What changes is the method: instead of Node2D speaking in two axes, we now use Node3D with three axes and Z depth. If you're comfortable with 2D, the transition to 3D will feel like adding one dimension, not replacing all your knowledge.
Episode 7's roadmap: we start from the basics of Node3D and transforms, then shape objects with meshes and materials, light the world with lighting, bring physics to life with 3D physics bodies and collision shapes, make characters able to walk with navigation, and finish with cameras, environments, skyboxes, and 3D model import with their animations.
All 3D nodes derive from Node3D. Their position is expressed in three axes: X (left-right), Y (up-down), and Z (forward-backward). In Godot, Y points up. Every Node3D has position, rotation, and scale properties combined into a transform — the combination of the three determines where and how an object is located.
Unlike 2D, transform order matters in 3D. A child node's position is always relative to its parent. So if you place a player at (0, 1, 0) under a root, and the root is rotated, the player rotates with it. This is the natural way to build 3D hierarchies: a character contains a weapon object, the weapon contains a muzzle flash, and so on.
extends Node3D
func _ready() -> void:
position = Vector3(2, 1, 0)
rotation_degrees = Vector3(0, 45, 0)
scale = Vector3.ONE * 1.5
func _process(delta: float) -> void:
rotate_y(delta)rotate_y(delta){gdscript} continuously rotates the node every frame — a common pattern for rotating objects like floating coins. If you've played with 2D, remember: everything Vector2 does in 2D, Vector3 now does in 3D.
An empty Node3D shows nothing until given a mesh — the geometry data (points, lines, triangles) that forms a surface. Godot provides built-in meshes like BoxMesh, SphereMesh, and CylinderMesh through the MeshInstance3D node, or meshes imported from Blender. The mesh determines the shape.
Material determines how the mesh's surface reflects light: its color, shininess, and texture. The most common material in Godot is StandardMaterial3D, which can be filled with properties like albedo_color and the albedo_texture texture. A MeshInstance3D may use its own material or override its mesh's material:
extends MeshInstance3D
func _ready() -> void:
mesh = BoxMesh.new()
mesh.size = Vector3(2, 0.5, 1)
var material := StandardMaterial3D.new()
material.albedo_color = Color(0.2, 0.6, 1.0)
material.metallic = 0.3
set_surface_override_material(0, material)Notice the metallic property — this is part of the PBR (Physically Based Rendering) concept. PBR materials mimic real light behavior: metallic determines how metallic the surface is, roughness determines how rough. Understanding these two numbers is the first step to making your 3D assets not look plastic.
Without light, a 3D scene is pitch black — because Godot computes lighting physically. There are several types of light nodes:
DirectionalLight3D — sunlight, parallel from one direction, hitting the entire scene.OmniLight3D — a light bulb, radiating from a single point in all directions.SpotLight3D — a cone beam, like a flashlight or stage light.extends DirectionalLight3D
func _ready() -> void:
rotation_degrees = Vector3(-45, 30, 0)
light_energy = 1.2
shadow_enabled = trueshadow_enabled = true{gdscript} enables shadows — the detail with the biggest impact on the sense of depth. Start with one DirectionalLight3D as the sun, then add OmniLight3D or SpotLight3D for mood and specific areas. Rule of thumb: don't stack too many lights, because each light costs render budget.
Godot's 3D physics exactly mirrors the 2D pattern, just with different names: CharacterBody3D, RigidBody3D, and StaticBody3D, all requiring a CollisionShape3D. A 3D floor is a StaticBody3D with a BoxShape3D or WorldBoundaryShape3D; a player is a CharacterBody3D with a CapsuleShape3D (the capsule shape fits human characters best).
extends CharacterBody3D
@export var speed := 5.0
func _physics_process(delta: float) -> void:
var direction := Vector3.ZERO
direction.x = Input.get_axis("move_left", "move_right")
direction.z = Input.get_axis("move_forward", "move_back")
direction = direction.normalized()
velocity.x = direction.x * speed
velocity.z = direction.z * speed
move_and_slide()In 3D, move_and_slide(){gdscript} works just like in 2D — moving the body and resolving collisions with floors and walls. Notice that movement direction is split per axis, and the vector is normalized so diagonal speed isn't faster than straight-line speed.
Navigation takes this further: instead of moving the character directly, NavigationAgent3D computes a path around obstacles on a NavigationRegion3D. After baking the region, call get_next_path_position(){gdscript} to get the next point to travel to, then steer velocity toward it:
extends CharacterBody3D
@onready var agent: NavigationAgent3D = $NavigationAgent3D
func _physics_process(delta: float) -> void:
var next := agent.get_next_path_position()
velocity = (next - global_position).normalized() * 4.0
move_and_slide()This pattern is called navigation following: the agent finds the path, you execute it. Very useful for enemies chasing the player or patrolling NPCs.
Warning
NavigationRegion3D requires baking first: set bake_navigation to true in the editor so Godot generates navigation data from the mesh geometry. Without baking, the agent won't know which way to go and the character will stay frozen.
In 3D, the camera is Camera3D. It can be free, or locked to follow a target like in 2D. The most common pattern is a third-person camera: a Camera3D node as a child of a "rig" node that follows the player. For a smoothly following camera, store the target position and interpolate:
extends Camera3D
@export var target: Node3D
func _process(delta: float) -> void:
global_position = global_position.lerp(target.global_position, 8.0 * delta)Then there's WorldEnvironment — the node that manages the scene's global lighting and atmosphere. Inside it you set up the environment: ambient light (fill light so dark areas aren't pitch black), fog, exposure, and tonemapping. The Skybox determines what's visible in the sky — either a PanoramaSkyMaterial panorama, or a ProceduralSkyMaterial that mimics a physical sky with sun and horizon.
extends WorldEnvironment
func _ready() -> void:
environment.background_mode = Environment.BG_SKY
environment.sky = ProceduralSkyMaterial.new()
environment.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
environment.ambient_light_energy = 0.3The order is simple: the camera determines what's seen, the environment determines how light behaves, and the skybox determines what stretches across the background. All three are required in almost every 3D scene so the result isn't dark or "floating in a void."
In 2D you animate sprites; in 3D you animate a skeleton — bones that drive the mesh. The workflow: the model is made in Blender (or Maya), exported as glTF (.gltf/.glb format), then imported into Godot. Godot converts it into a MeshInstance3D for geometry, a Skeleton3D for bones, and an AnimationPlayer for the baked animations.
glTF is the recommended format: it carries the mesh, materials, skeleton, and animations in a single file. After import, animations appear as tracks in the AnimationPlayer and can be played exactly like in episode 6:
extends AnimationPlayer
func _ready() -> void:
play("run")
func _input(event: InputEvent) -> void:
if event.is_action_pressed("jump"):
play("jump")If the model looks black or confusing, check two things: whether the StandardMaterial3D has an albedo texture, and whether the scene scale makes sense — Godot uses meters as its unit, so a 2-meter-tall character in Blender should be about 1.8 meters in Godot. Wrongly scaled models are the most common cause of physics bugs in 3D.
Episode 7 introduced all the pillars of 3D games: Node3D and three-axis transforms, meshes with PBR materials, lighting with DirectionalLight3D, 3D physics bodies with CollisionShape3D, navigation with NavigationAgent3D, plus Camera3D, WorldEnvironment, skyboxes, and the glTF model import workflow with skeletal animation.
The key takeaways:
Vector3.metallic and roughness for reasonable PBR results.DirectionalLight3D and enable shadows; add more lights only when needed.CapsuleShape3D is the best default for characters.In episode 8, you take a break from the world and learn to convey information: UI & HUD Development. We'll dissect Control nodes, containers and layouts, buttons and labels, responsive anchoring, and connecting UI signals to game logic. See you on the interface screen!