Quick answer: CanvasLayer ignores Camera2D by default. Set follow_viewport_enabled = true and tune follow_viewport_scale for parallax. For HUDs leave both at default. For a parallax background, set scale 0.5; for full world-space sync set scale 1.0.
Here is how to fix Godot CanvasLayer nodes that ignore the active Camera2D. You drop a parallax background under a CanvasLayer to keep its drawing order separate, but the moment the camera moves, the background drifts off-screen. CanvasLayer is screen-space by design, and you have to opt in to viewport tracking with two specific properties.
The Symptom
A CanvasLayer hosts background sprites. As the player moves and the Camera2D follows, the background slides relative to the world — either staying glued to screen (you wanted parallax) or jumping off-screen (you wanted world-locked).
What Causes This
Default CanvasLayer is screen-space. CanvasLayer was built for HUDs, which need to ignore the camera. Without explicit follow settings, it stays glued to viewport coordinates regardless of camera position.
follow_viewport_scale not configured. Even with follow enabled, you need a non-zero scale for visible movement. The default is 1.0; if set to 0 the layer stays put.
Multiple cameras. If you have several Camera2Ds and the wrong one is active, the layer follows the wrong camera. make_current() on the right camera fixes it.
Camera2D smoothing artifacts. Smoothing produces sub-pixel motion that interacts visibly with parallax layers. Tearing or wobble across pixel boundaries.
The Fix
Step 1: Enable follow_viewport_enabled.
extends CanvasLayer
func _ready():
follow_viewport_enabled = true
follow_viewport_scale = 0.5 # Parallax background
Or set both in the inspector. The CanvasLayer now respects the current Camera2D.
Step 2: Tune scale per layer.
# Far background
$BackgroundLayer.follow_viewport_enabled = true
$BackgroundLayer.follow_viewport_scale = 0.2
# Mid background
$MidLayer.follow_viewport_enabled = true
$MidLayer.follow_viewport_scale = 0.5
# Foreground - moves at full camera speed
$FgLayer.follow_viewport_enabled = true
$FgLayer.follow_viewport_scale = 1.0
# HUD - ignores camera entirely
$HUDLayer.follow_viewport_enabled = false
Step 3: Snap to pixels for crisp parallax. Open Project Settings → Rendering → 2D → Snap 2D Transforms To Pixel and enable. This rounds layer positions to whole pixels, eliminating shimmer when sub-pixel parallax meets pixel-art sprites.
Step 4: Disable Camera2D smoothing if it interacts badly. Smoothing introduces sub-pixel positions that the layer dutifully replicates, leading to visible jitter. Either disable smoothing, or enable both Snap 2D Transforms options to keep things on integers.
# In Camera2D inspector
position_smoothing_enabled = false
# Or pair with Snap 2D Transforms enabled in project settings
Step 5: Use ParallaxBackground for traditional parallax. If you have multiple layers all parallaxing at different rates, ParallaxBackground + ParallaxLayer nodes provide built-in tiling and motion factors. They are slightly higher level than rolling your own with CanvasLayer.
# Scene structure
ParallaxBackground
ParallaxLayer (motion_scale = 0.2, motion_mirroring = (1024, 0))
Sprite2D (sky.png)
ParallaxLayer (motion_scale = 0.5, motion_mirroring = (1024, 0))
Sprite2D (mountains.png)
When To Use CanvasLayer Vs ParallaxBackground
ParallaxBackground is purpose-built for endless side-scrolling. CanvasLayer with follow_viewport gives you finer-grained control: you can mix world-space sprites and screen-space UI in the same layer, you can change scale at runtime, and you can stack layers in arbitrary draw order. For pure parallax, ParallaxBackground is simpler. For mixed UI and world overlays, CanvasLayer wins.
“CanvasLayer is screen-space until told otherwise. Two flags turn it into a parallax host.”
Related Issues
For Camera2D smoothing problems, see CharacterBody2D Ghost Collision. For other rendering issues, see CollisionShape Disabled.
follow_viewport_enabled = true. Then pick a scale. The layer moves with intent.