Instance of a Spawner dont emit signal

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

Hi !

I’ve been making random spawners for a power up in my top-down game.
I have a problem with one of them.

when I originally created the power up, I made it so when the Player collides with it, it emits a signal then queue_free(). The signal then tells the player to be faster for a few seconds.

The problem that I have is that now that the power up comes ou of a spawner, the Player doesnt recognize the signal…

What should I do ?

Here is the code for the power up emiting signal:

    
func _on_speed_up_body_entered(body: Node) -> void:
	emit_signal("speed_up")
	queue_free()

and here is the code for the player when he hears the signal:

func _on_speed_up_speed_up() -> void:
	$Power_upstimer.start(2)
	max_speed = 120

Thanks a lot !!

:bust_in_silhouette: Reply From: skysphr

There are several ways to do it.

First consider if you want to implement the powerup code within the powerups or within the player. A rule of thumb is: if the powerup can affect more actors in the same way, it might make sense to have the code inside powerups, to avoid duplication. If the powerup can affect multiple actors but in different ways, the actors should implement it separately. If powerups can only ever affect one actor, it really depends on the context of your project architecture.

If you want to implement the collision on the player end, use your method of choice for collision detection (for KinematicBody use the KinematicCollision2D provided by the movement methods; for a player whose collision is implemented via Area2D, simply connect the area_enter signal). To identify weather the colliding area is indeed a powerup, you could set the powerups’ class_name and then:

func _on_collision(body: Area2D):
    if body is Powerup:
        ...

You could also use groups - if body.is_in_group("powerups"):, or object metadata - if body.has_meta("powerup").

A similar approach could be done on the powerup side; you could either have the spawner connect your collision directly to the player (assuming the spawner has a direct reference to the player), however this could be bad practice unless you absolutely know for sure that there is only ever going to be one and only player. Alternatively you could have the powerup’s area scan for any incoming body_entered or area_entered signals, identify the collisionee and act accordingly.

To better understand possibilities of inter-object communication, you might want to read the scene organization best practices article from the docs.

Edit: hopefully fixed formatting

Thanks for your really good answer ! however, I dont know how to make a class. in fact, i’ve never heard of that. It is simple ?

dany_pitre | 2021-09-20 23:46

Any script is technically a class. You only need to type class_name Something on top to make it globally accessible. Fun fact: you can also write class_name Name, "res://some_icon" to give the thing a custom icon for extra satisfaction.

skysphr | 2021-09-20 23:51

Thanks ! It dosent seems to work… there is probably something i did wrong.

I tries putting the object in a group, and in a class.

I wrote this in the object code:

class_name Speed_up

and that in my player’s code:

if body is Speed_up:
	$Power_upstimer.start(2)
	max_speed = 120
	body.queue_free()
	

dany_pitre | 2021-09-21 00:01

What is the method in which you are running that? It has to be a generic collision detection function, not something that is only being triggered by a signal from the collided object, as it was most likely the case in your initial architecture.

skysphr | 2021-09-21 01:31