Documentation Index Fetch the complete documentation index at: https://mintlify.com/godotengine/godot/llms.txt
Use this file to discover all available pages before exploring further.
CanvasLayer Overview
CanvasLayer nodes render their children on separate rendering layers, independent of the camera and scene hierarchy. They’re primarily used for:
UI overlays (HUD, menus)
Parallax backgrounds
Foreground effects
Multi-layered scenes
Basic CanvasLayer
Creating a UI Layer
extends CanvasLayer
func _ready ():
# Set layer index (higher = drawn on top)
layer = 1
# Make visible
visible = true
Layer Ordering
Layers are drawn in order of their layer property:
# Background layer
background_layer . layer = - 1
# Game layer (default is 0)
game_layer . layer = 0
# UI layer
ui_layer . layer = 1
# Debug overlay
debug_layer . layer = 2
Embedded windows are on layer 1024. Layers 1025+ appear above embedded windows.
UI with CanvasLayer
Basic HUD Setup
Game (Node2D)
├── Level (Node2D)
│ ├── Player
│ └── Enemies
└── HUD (CanvasLayer)
├── HealthBar
├── ScoreLabel
└── PauseButton
Example HUD Script
extends CanvasLayer
@onready var health_bar = $ HealthBar
@onready var score_label = $ ScoreLabel
func _ready ():
layer = 1 # Above game content
func update_health ( value : int ):
health_bar . value = value
func update_score ( value : int ):
score_label . text = "Score: %d " % value
Following the Viewport
# Layer stays fixed on screen (default)
follow_viewport_enabled = false
# Layer follows camera in world space
follow_viewport_enabled = true
follow_viewport_scale = 1.0 # Adjust scale for parallax effect
CanvasLayer has its own transform, independent of the scene:
extends CanvasLayer
func _ready ():
# Offset the entire layer
offset = Vector2 ( 10 , 10 )
# Rotate the layer
rotation = deg_to_rad ( 5 )
# Scale the layer
scale = Vector2 ( 1.5 , 1.5 )
func shake ():
# Shake effect for the whole layer
var tween = create_tween ()
tween . tween_property ( self , "offset" , Vector2 ( randf_range ( - 5 , 5 ), randf_range ( - 5 , 5 )), 0.05 )
tween . tween_property ( self , "offset" , Vector2 . ZERO , 0.05 )
Custom Viewport
# Assign specific viewport
custom_viewport = $ SubViewport
# Use default viewport
custom_viewport = null
ParallaxBackground
ParallaxBackground creates parallax scrolling effects for backgrounds.
ParallaxBackground is deprecated in favor of Parallax2D. However, it’s still widely used and functional.
Basic Setup
Level (Node2D)
├── ParallaxBackground
│ ├── ParallaxLayer (Sky)
│ │ └── Sprite2D
│ ├── ParallaxLayer (Clouds)
│ │ └── Sprite2D
│ └── ParallaxLayer (Mountains)
│ └── Sprite2D
├── TileMap
└── Player
ParallaxBackground Properties
extends ParallaxBackground
func _ready ():
# Scroll offset (usually controlled by camera)
scroll_offset = Vector2 ( 0 , 0 )
# Base offset for all layers
scroll_base_offset = Vector2 ( 0 , 0 )
# Base scale for all layers
scroll_base_scale = Vector2 ( 1 , 1 )
# Ignore camera zoom
scroll_ignore_camera_zoom = false
# Scroll limits
scroll_limit_begin = Vector2 ( 0 , 0 )
scroll_limit_end = Vector2 ( 0 , 0 )
extends ParallaxBackground
func _process ( delta ):
# Manual scroll control
scroll_offset . x += 50 * delta
ParallaxLayer
ParallaxLayer must be a child of ParallaxBackground. Each layer moves at a different rate.
Motion Scale
extends ParallaxLayer
func _ready ():
# Move at half speed (far background)
motion_scale = Vector2 ( 0.5 , 0.5 )
# Move at double speed (foreground)
# motion_scale = Vector2(2.0, 2.0)
# No horizontal movement
# motion_scale = Vector2(0, 1)
Motion Offset
# Initial offset
motion_offset = Vector2 ( 100 , 0 )
extends ParallaxLayer
func _ready ():
# Repeat texture every 512 pixels horizontally
motion_mirroring = Vector2 ( 512 , 0 )
# No vertical mirroring
# motion_mirroring.y = 0
For pixel-perfect mirroring, set motion_mirroring to match your background sprite’s width.
Complete Parallax Example
# ParallaxBackground.gd
extends ParallaxBackground
func _ready ():
layer = - 100 # Behind everything
# Sky Layer (ParallaxLayer)
# motion_scale = Vector2(0.1, 0.1)
# motion_mirroring = Vector2(1024, 0)
# Cloud Layer (ParallaxLayer)
# motion_scale = Vector2(0.3, 0.3)
# motion_mirroring = Vector2(768, 0)
# Mountain Layer (ParallaxLayer)
# motion_scale = Vector2(0.6, 0.6)
# motion_mirroring = Vector2(512, 0)
With Camera2D
When using Camera2D, the parallax updates automatically:
Player (CharacterBody2D)
├── Camera2D
└── Sprite2D
Level (Node2D)
└── ParallaxBackground
├── SkyLayer (ParallaxLayer)
├── CloudLayer (ParallaxLayer)
└── MountainLayer (ParallaxLayer)
Multi-Layer Scene Example
# Game structure with multiple canvas layers
extends Node2D
func _ready ():
# Background parallax
var bg = $ BackgroundLayer
bg . layer = - 1
# Main game layer (default, layer 0)
# Contains player, enemies, etc.
# UI overlay
var ui = $ UILayer
ui . layer = 1
# Pause menu
var pause = $ PauseLayer
pause . layer = 2
pause . visible = false
func _input ( event ):
if event . is_action_pressed ( "pause" ):
toggle_pause ()
func toggle_pause ():
var pause_layer = $ PauseLayer
pause_layer . visible = ! pause_layer . visible
get_tree (). paused = pause_layer . visible
Advanced: Dynamic Parallax
extends ParallaxLayer
var base_motion_scale = Vector2 ( 0.5 , 0.5 )
func _process ( delta ):
# Change parallax speed based on player state
var player = get_tree (). get_first_node_in_group ( "player" )
if player :
if player . is_running :
motion_scale = base_motion_scale * 1.5
else :
motion_scale = base_motion_scale
Visibility Control
# Hide entire layer and children
visible = false
# Show layer
visible = true
# Toggle visibility
func toggle_layer ():
visible = ! visible
# Fade layer
func fade_out ():
var tween = create_tween ()
tween . tween_property ( self , "modulate:a" , 0.0 , 1.0 )
func fade_in ():
var tween = create_tween ()
tween . tween_property ( self , "modulate:a" , 1.0 , 1.0 )
Canvas Layer for Screen Effects
extends CanvasLayer
@onready var color_rect = $ ColorRect
func _ready ():
layer = 10 # Very high layer
color_rect . color = Color ( 0 , 0 , 0 , 0 )
func flash_white ():
var tween = create_tween ()
tween . tween_property ( color_rect , "color" , Color . WHITE , 0.1 )
tween . tween_property ( color_rect , "color" , Color ( 1 , 1 , 1 , 0 ), 0.1 )
func fade_to_black ():
var tween = create_tween ()
tween . tween_property ( color_rect , "color" , Color . BLACK , 1.0 )
Split-Screen with CanvasLayers
# Each viewport needs its own CanvasLayer setup
# Player 1 Viewport
var viewport1 = SubViewport . new ()
var canvas1 = CanvasLayer . new ()
canvas1 . custom_viewport = viewport1
# Player 2 Viewport
var viewport2 = SubViewport . new ()
var canvas2 = CanvasLayer . new ()
canvas2 . custom_viewport = viewport2
Best Practices
Use CanvasLayer for all UI
Always put UI elements in a CanvasLayer to keep them independent of the game camera.
Set appropriate layer indices
Organize layers logically: backgrounds (-1), game (0), UI (1+), overlays (high numbers).
Keep parallax layers simple
Too many parallax layers can hurt performance. Use 3-5 layers maximum.
Match mirroring to sprite size
For seamless scrolling, set motion_mirroring to exactly match your sprite width.
One ParallaxBackground per viewport
Each viewport needs its own ParallaxBackground for split-screen games.
Troubleshooting
Check that layer is higher than game content and visible is true.
Ensure there’s a Camera2D in the scene, or manually update scroll_offset.
Verify motion_mirroring matches sprite width exactly, and sprite edges tile seamlessly.
Set follow_viewport_enabled = false to fix UI in screen space.
Next Steps
2D Overview Revisit 2D fundamentals and camera systems
Sprites and Textures Learn more about displaying graphics