Quick answer: A CanvasLayer ignores the camera by design. For world-anchored or parallax content, set follow_viewport_enabled = true and use follow_viewport_scale for the parallax factor.
A background CanvasLayer is meant to parallax-scroll behind the world, but it stays locked to the screen — or the offset is wrong when the camera moves.
CanvasLayers Are Screen-Space by Default
A CanvasLayer renders independently of the 2D camera — that’s the point for HUDs. But it means a background layer won’t move with the world unless you tell it to.
Enable Follow Viewport
$BackgroundLayer.follow_viewport_enabled = true
$BackgroundLayer.follow_viewport_scale = 0.5 # half-speed parallax
- follow_viewport_enabled: the layer now tracks the camera.
- follow_viewport_scale: 1.0 moves with the world; <1.0 lags behind (far parallax); >1.0 moves faster (foreground parallax).
Or Use Parallax2D / ParallaxBackground
For multi-layer scrolling backgrounds, the dedicated Parallax2D (Godot 4.3+) or ParallaxBackground nodes handle the math — you set a scroll scale per layer and they follow the camera automatically.
Keep HUD Layers As-Is
Your HUD CanvasLayer should keep follow_viewport off — it’s meant to be screen-locked. Only enable following on layers that represent world content.
Verifying
Move the camera. Background layers scroll at their parallax rates; the HUD stays put. No drift, no wrong offset.
“CanvasLayers ignore the camera on purpose. Opt in with follow_viewport for world-anchored layers.”
For anything beyond one parallax layer, reach for Parallax2D — hand-rolling follow_viewport_scale per layer gets fiddly fast.