All lessons
Lesson 22

Walking Behind Things

Walk up behind a tree and disappear behind it, then come back down in front. One checkbox gives a flat top-down world a sense of depth.

Loading the game engine. This takes a moment the first time.

Top-down only

script at all.

Walk UP behind a tree and you go behind it. Walk back DOWN and you are in front of it again. Nothing in this file does that. The level's root node has "Y Sort Enabled" ticked, so every frame Godot draws whatever is lower on the screen in front of whatever is higher up. That is how a top-down world gets a sense of depth.

Notice what is NOT here: this player does not set z_index. A z_index is a fixed layer number, so it would pin the player in front of every tree forever and Y sorting would never get a say.

Each tree's origin sits at the BOTTOM of its trunk, which is what makes the sorting look right. Y sorting compares those origin points, so putting a tree's origin at its base means "how far down is this tree standing?"

The scenes

UI node · 2D node · % unique name · .tscn instanced scene

y_sorting.tscn
  • YSorting Node2D
  • Player CharacterBody2D player.tscn
  • Tree1 StaticBody2D tree.tscn
  • Tree2 StaticBody2D tree.tscn
  • Tree3 StaticBody2D tree.tscn
  • Tree4 StaticBody2D tree.tscn
  • Tree5 StaticBody2D tree.tscn
player.tscn
  • Player CharacterBody2D player.gd
  • Sprite2D
  • CollisionShape2D
tree.tscn
  • Tree StaticBody2D
  • Trunk Polygon2D
  • Canopy Polygon2D
  • CollisionPolygon2D
extends CharacterBody2D

## How fast the player moves. "@export" puts "speed" at the top of the
## Inspector panel, so you can change it there instead of in this file.
@export var speed: float = 200.0

# "_physics_process()" runs about 60 times a second. Godot calls it for you.
func _physics_process(_delta: float) -> void:
	# "Input.get_vector(...)" checks all four keys at once and turns them
	# into one arrow pointing where you want to go. The names in quotes are
	# Godot's built-in names for the arrow keys.
	var direction: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	# "direction" is only WHICH WAY (its length is always 1).
	# "direction * speed" stretches it, so "velocity" is also HOW FAST.
	velocity = direction * speed
	# Nothing moves until "move_and_slide()" runs.
	move_and_slide()

	# The warrior picture only faces right, so walking left mirrors it and
	# walking right puts it back.
	if direction.x < 0.0:
		$Sprite2D.flip_h = true
	if direction.x > 0.0:
		$Sprite2D.flip_h = false