Quick answer: Set the HUD CanvasLayer.layer to at least 1 (default is 0). Layer ordering wins over z_index — even a TileMap with z_index 100 sits below a CanvasLayer with layer 1.

You drop a label into a CanvasLayer, parent it to the root, and run the game. The TileMap is rendering over the top of the label. You bump z_index on the label. Nothing changes. You bump it to 1000. Still hidden. The reason is that layer beats z_index in Godot’s 2D ordering rules — and the layer defaults to 0.

The Three-Tier Sort Order

Godot 2D drawing is sorted in this order:

  1. CanvasLayer.layer — higher draws later (on top). Default 0.
  2. Node z_index — within a layer, higher draws later. Default 0.
  3. Scene tree order — within the same z_index, later siblings draw on top.

This means a TileMap with z_index 5 on layer 0 will draw below any node on layer 1, regardless of z_index. The layer index trumps the z_index.

The Fix

Open the HUD CanvasLayer in the scene tree, select it, and in the Inspector set Layer to 1 (or higher):

# hud.tscn structure
HUD (CanvasLayer)
  layer = 1            # the critical value
  follow_viewport_enabled = false
  ScoreLabel (Label)
  HealthBar (TextureProgressBar)

Layers can be negative. A common pattern is:

When the TileMap Itself Sets a z_index

If you set z_index on the TileMap to a large positive value (sometimes done to layer ground tiles above props), this only affects nodes on the same CanvasLayer. It cannot push the TileMap above a different CanvasLayer. A common confusion: developers set TileMap z_index to 100 to overlap entities, then later wonder why their HUD on layer 1 still wins. It always will.

When You Have Multiple HUDs

For a pause menu that should cover the HUD when active, give it a higher layer:

# pause_menu.tscn
PauseMenu (CanvasLayer)
  layer = 2
  process_mode = Node.PROCESS_MODE_ALWAYS   # runs while paused

When the player resumes, set the CanvasLayer’s visible = false — or queue_free it — rather than swapping layers, which would be confusing to maintain.

follow_viewport_enabled and Parallax

CanvasLayer has a follow_viewport_enabled property. With it off (default), the layer ignores the camera entirely — perfect for HUDs. With it on, the layer follows the viewport but with a configurable scale, giving you a fast parallax effect. Keep HUD layers with follow_viewport_enabled = false so they never appear to scroll when the camera moves.

Verifying

Toggle the HUD CanvasLayer’s visibility in the editor. The TileMap should draw normally with it off; the HUD should sit cleanly on top with it on. If the HUD still looks clipped or sandwiched, look for a third CanvasLayer in your scene (sometimes added implicitly by a parent autoload like a transition fader) with a higher layer index.

“Layer beats z_index. z_index beats tree order. Once you internalize that, half your draw-order bugs disappear.”

Adopt the −1/0/1/2/3 layer convention project-wide — future-you will appreciate it.