How to pass a variable and extend a _unhandled_input()?

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

Using Godot 3.1, I have func _unhandled_input(event):

I want to use this function in so many sprites

So sprite1, it has to be attached as a script to it and so one, for each sprite I need to use that function on, it needs to be attached to the sprite

func _unhandled_input(event):
	if play == True:
		if (event is InputEventMouseButton and event.pressed and not event.is_echo() and event.button_index == BUTTON_LEFT) or (event is InputEventScreenTouch):
			if get_rect().has_point(to_local(event.position)):
				#code here
				get_tree().set_input_as_handled() 

I want to pass a variable to it on every different sprite, the problems that I have

  1. I cannot pass variables to it, it only accepts event as an argument
  2. I cannot put it in another function
  3. I cannot as far as I know extend it
  4. I cannot store it in a global script file, it needs to be attached to a parent node
  5. I don’t want to copy paste

Can’t you use the same script on each sprite? You could add an exported variable to change this “sprite specific” argument. What do you mean by expand?

Jowan-Spooner | 2019-05-27 09:14

@Jowan-Spooner definitely has the right approach to this. You can make it slightly more extensible also by calling out to a virtual method where you have “#code here” if you wanted to, which you can then override in inherited scripts, if there was functionality that had to change drastically based on the sprite handling the click. See my answer on Facebook for more.

Kyle Szklenski | 2019-05-27 10:21

:bust_in_silhouette: Reply From: Kolaru

You can use a “trait-like” trick.

Create a new scene or node class (say InputHandlerTrait) with a script defining _unhandled_input, in such a way that it acts on his direct parent. Here for example I modified your code to get the rect of its parent:

func _unhandled_input(event):
    if play == True:
        if (event is InputEventMouseButton and event.pressed and not event.is_echo() and event.button_index == BUTTON_LEFT) or (event is InputEventScreenTouch):
            if get_parent().get_rect().has_point(to_local(event.position)):
                # do stuff on parent
                get_tree().set_input_as_handled() 

Now every sprite which have a InputHandlerTrait as a direct child will use this behavior and by extending the class or adding exported variable, you can customize it as you wish.

Note however that to get event you may want to consider adding an Area2D to your node (maybe setting it automatically to the sprite rect) and use the signal it emits to handle the input.