Godot Version
4.7.1
Question
Hi! I’m having trouble creating a pause menu that opens submenus using canvas layers. I’ve been following jorge robles JRPG tutorial and got up to the inventory system which uses a canvas layer to create the UI.
I wanted to change how the inventory was opened to a system closer to what you might find in an rpgmaker project. So open pause menu → pressbutton → Open adjacent interactable screen. Press esc to back out to pause, then esc again to return to game.
I though I would be able to simply connect up the pause menu buttons to the open() function in the inventory screen with Signals. I made sure my PauseMenu scene is an Autoload so I can eventually send signals to other screen scenes. But It doesn’t show at all. I’m not sure where I’m going wrong.
PauseMenu Script:
extends CanvasLayer
@onready var _panel: PanelContainer = $PanelContainer
signal call_inv
func _ready() -> void:
_panel.visible = false
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") and get_tree().paused:
_resume()
get_viewport().set_input_as_handled()
elif event.is_action_pressed("pause") and !get_tree().paused:
_pause()
get_viewport().set_input_as_handled()
func _resume() -> void:
get_tree().paused = false
_panel.visible = false
func _pause() -> void:
get_tree().paused = true
_panel.visible = true
$PanelContainer/VBoxContainer/Resume.grab_focus.call_deferred()
func _on_resume_pressed() -> void:
_resume()
func _on_inventory_pressed() -> void:
call_inv.emit()
InventoryScreen Script:
extends CanvasLayer
## The inventory screen. Opens/closes with the menu key.
const itemSlotScene := preload("res://ui/inventory/item_slot.tscn")
#region @onready
@onready var _panel: PanelContainer = $PanelContainer
@onready var _item_grid: GridContainer = $PanelContainer/MarginContainer/VBoxContainer/ItemGrid
@onready var _gold_label: Label = $PanelContainer/MarginContainer/VBoxContainer/Header/GoldLabel
@onready var _description_label: RichTextLabel = $PanelContainer/MarginContainer/VBoxContainer/DescriptionLabel
#endregion
var _is_open: bool = false
func _ready() -> void:
_panel.visible = false
#PauseMenu Signal
PauseMenu.call_inv.connect(open)
InventoryManager.inventory_changed.connect(_refresh)
InventoryManager.gold_changed.connect(_on_gold_changed)
_update_gold_display()
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel") or event.is_action_pressed("menu") and _is_open: # Close Inventory
close()
get_viewport().set_input_as_handled()
elif event.is_action_pressed("menu") and not _is_open:
# Old open code
open()
get_viewport().set_input_as_handled()
func open() -> void:
_show()
func _show() -> void:
_is_open = true
_panel.visible = true
#get_tree().paused = true (Removed as pausing is handled in PauseMenu)
_refresh()
PauseMenu:
- Process Mode: Always
- CanvasLayer Layer: 1
InventoryScreen:
- Process Mode: When Paused (Idea being that it can only be accessed when Pause menu is open)
- CanvasLayer Layer: 2
I feel like I must have misunderstood how Signals or CanvasLayers work. Or both of them. Any advice would be appreciated, thank you!


