Same script, multiple instances

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

I created a Player scene and attached a script to it. To my understanding, I thought that like OOP, if I add multiple instances of the same player scene to my main scene, each of them will operate like a unique instance and will have its own script instance so that every signal sent to this script will be sent to X instances of player scenes I have.

That’s not the case… I emit a signal from my main scene script and it received on the player script once, for all instances of player in the scene.

Maybe I misunderstood and this is not possible to begin with but if it does, how? and if not, what would you suggest to be a solution to such a case?

I emit a signal from my main scene script and it received on the player script once, for all instances of player in the scene.

I don’t understand how that’s different from

every signal sent to this script will be sent to X instances of player scenes I have.

If all your players are connected to the same signal, when that signal emits, all players will receive it.

Do you mean only ONE of your players receive it?

Zylann | 2019-08-22 12:42

All my players receive it so doing something that should affect only one of them is impossible.
I ended up sending multiple signals with the player object as a param to check if player.name == self.name and do the action only for it.
Is this the way to go?

lioriluz | 2019-08-22 13:03

You can choose which is connected and which isn’t. If you want some players to never receive the signal, just disconnect it from these instances. Or don’t make the connection in the first place, depends how you connected the signal.

Zylann | 2019-08-22 18:45

I want all the players to receive the signal but handle it uniquely for each of them. Do I have to emit the signal X times or is there an option to emit it once and somehow handle it per Player?

lioriluz | 2019-08-22 19:15

Sorry I still don’t understand what you really want. Signals are connected to whichever you want, and when you emit it once, it gets sent to whoever is connected to it at the time. The emitter can send arguments as well. There is also a way to specify extra arguments at connection time, which expand the emit-time arguments.

I ended up sending multiple signals with the player object as a param to check if player.name == self.name

I don’t understand the point of this either. If you want to send a message to a particular player, just call a function on that player, don’t use signals. Or connect the signal only to that player.

Zylann | 2019-08-22 19:22

Thanks for taking the time to answer although I wasn’t clear enough. @Zylann

Maybe some code will help.
Main scene script:

func stop():
	emit_signal("touch")

Player script:

func _on_Main_touch():
# Do whatever

In this way, _on_Main_touch() will be called once per player which is great but I don’t have any way I know of to do handle it differently per player instance. For example: Player1 should go right, Player2 should go left and Player3 should go up.

So I moved to:
Main scene script:

func stop():
	for player in get_tree().get_nodes_in_group("players"):
			emit_signal("touch", player)

Player script:

func _on_Main_touch(location, player):
      if (player.get_name() == self.get_name()):
      #Do something else per player

This way works for my logic but _on_Main_touch is called way more than needed (4 times per player as there are 4 players in that node group).

Are any of the above is the right way to go? Any better ways?

lioriluz | 2019-08-23 17:55

for player in get_tree().get_nodes_in_group("players"):
        emit_signal("touch", player)

Considering what you want to do, this is obviously not the right solution. Keep it with a single emit_signal.

So all your players will receive the signal touch. Great. Now you want each of them to do something different: based on what?
You gave an example where Player1 should go right, Player2 should go left and Player3 should go up. So the solution to that would litterally be:

func _on_Main_touch():
	if name == "Player1":
		# Go right
	elif name == "Player2":
		# Go left
	elif name == "Player3":
		# Go up

If it’s more complex than that, maybe you need different scripts with a common base script, or you could connect to a different function, or specify connect-time arguments (with the signal “bindings”).

Zylann | 2019-08-23 18:41

Thanks! I misunderstood signals it seems, now I get it and it works.

lioriluz | 2019-08-23 19:40