Working around set_process(false) to avoid two scripts using the same input at the same time

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Deith

Tree structure:

MenuController.tscn
|----SubMenu.tscn
|----SubMenu2.tscn

I have a script called MenuController.gd (attached to MenuController.tscn) which in short runs like this:

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
        subMenu.is_active = true
        subMenu.visible = true

And subMenu.tscn which is a child node of MenuController.tscn I have a subMenu.gd script which checks:

func _process(delta):
    if is_active:
        # Do stuff here
        if Input.is_action_just_pressed("ui_accept"):
            # do something here

And the obvious problem is that one "ui_accept" action triggers both checks because on the same input the game changes is_active to true in MenuController.gd and the same input is used to check in SubMenu.gd to perform # do something here because is_active is at this point true. It is because both scripts are always running. I solved this by just doing subMenu.set_process(false) and changing MenuController.gd check to:

func _process(delta):
    if Input.is_action_just_pressed("ui_accept"):
       subMenu.is_active = true
       subMenu.set_process(true)
       subMenu.visible = true

This way the subMenu is not doing anything unless I activate it. But. It doesn’t seem like a good clean solution, more like hacking around good practise. What would be the correct solution here?

It seems fine to me, but I’d avoid using set_process(), since if you already have is_active it doesn’t seem needed. Or why not just remove SubMenu if it’s not currently needed, and re-add it when required?

SteveSmith | 2022-09-29 11:44

:bust_in_silhouette: Reply From: BoxyLlama

Option 1 :
Add a check for whether the Submenu is active when checking input in the Menu Controller:

MenuController.gd

func _process(delta):
  if Input.is_action_just_pressed("ui_accept") and subMenu.is_active == false:
    subMenu.is_active = true
    subMenu.visible = true

Option 2 :
Consider moving the intput check out of _process and into _unhandled_input. This is called bottom up, so the sub-menu would check first. Set the input to processed. And the MenuController will ignore it.

MenuController.gd

func _unhandled_input(event):
  if event.is_action_just_pressed("ui_accept"):
      subMenu.is_active = true
      subMenu.visible = true

SubMenu.gd

func _unhandled_input(event):
  if is_active:
      # Do stuff here
      if event.is_action_just_pressed("ui_accept"):
          # do something here
          get_tree().set_input_as_handled() // Call to set this event as handled

Went with Option 2 since I don’t really need to check inputs in _process, and it works. Thank you very much.

Deith | 2022-09-29 15:27