Signal not working on first collision

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

I’m working on a infinite runner where you have scenarios with different colors and the player must take an item to change it’s skin to match the next scenario color. I made the items and the code for the player to change skin according to item color.

The way i did it was using colliders in the items and the player and as soon as one of the items is hit a signal is sent to the main node in and then connected to a function in the player’s script to change it’s skin.

The problem is that when i hit play the colliders work perfectly but the signal is only connected after the second collision, so when the player hits the first item nothing happens.

Here goes some code and prints:

The scenario scene (it chooses a random background texture when spawned):

The code for the scenario:

extends Node2D

# Preloading the images for the items sprites
var green_item = preload('res://sprites/scenario/itemGreen.png')
var red_item = preload('res://sprites/scenario/itemRed.png')
var purple_item = preload('res://sprites/scenario/itemPurple.png')
var blank_item = preload('res://sprites/scenario/itemBlank.png')

# Preloading the images for the scenarios sprites
var green_background = preload('res://sprites/scenario/scenario_green.png')
var red_background = preload('res://sprites/scenario/scenario_red.png')
var purple_background = preload('res://sprites/scenario/scenario_purple.png')

# Creating an array of possible background sprites
var background_sprites = [green_background, red_background, purple_background]
# Variable keep the last spawned scenario sprite stored
var selected_background_sprite

# Signal to send the index of the item color to the player
signal send_index

# To get an index out of a value
var index_dictionary = {green_item : 0, red_item : 1, purple_item : 2, blank_item : null}

# To randomize sprites
var item_sprites = [green_item, red_item, purple_item]

func _ready():
	randomize()
	
	# A background sprite will be picked
	selected_background_sprite = floor(rand_range(0, floor(background_sprites.size())))
	# If this background color is the same as the previous all the itens get tranparent sprites
	if(Global.previous_background_texture == selected_background_sprite):
		$SwitchAreas/Switch1/Sprite.texture = blank_item
		$SwitchAreas/Switch2/Sprite.texture = blank_item
		$SwitchAreas/Switch3/Sprite.texture = blank_item
		pass
	# Else shuffles the array of item sprites and apply then to the itens
	else:
		item_sprites.shuffle()
		
		$SwitchAreas/Switch1/Sprite.texture = item_sprites[0]
		$SwitchAreas/Switch2/Sprite.texture = item_sprites[1]
		$SwitchAreas/Switch3/Sprite.texture = item_sprites[2]
	
	
	# Send the selected scenario sprite to the global script to control what was the previous sprite
	Global.previous_background_texture = selected_background_sprite
	# Applying the selected sprite to the background
	$Background.texture = background_sprites[selected_background_sprite]
	
	# Sending it's name to the glabal script in order to connect the signal later
	Global.node_name = self.name

# When player collides with item 1
func _on_Switch1_body_entered(player):
	# Set's collision boolean checker in global script
	Global._on_colision_detection()
	# emits the signal with the index of this item color
	emit_signal("send_index", index_dictionary[$SwitchAreas/Switch1/Sprite.texture])
	# Call a method to destroy the colliders in this scene to prevent hitting two items or hit the same twice
	_destroy_items_collision()
	pass 

# When player collides with item 2
func _on_Switch2_body_entered(player):
	# Set's collision boolean checker in global script
	Global._on_colision_detection()
	# emits the signal with the index of this item color
	emit_signal("send_index", index_dictionary[$SwitchAreas/Switch2/Sprite.texture])
	# Call a method to destroy the colliders in this scene to prevent hitting two items or hit the same twice
	_destroy_items_collision()
	pass 

# When player collides with item 3
func _on_Switch3_body_entered(player):
	# Set's collision boolean checker in global script
	Global._on_colision_detection()
	# emits the signal with the index of this item color
	emit_signal("send_index", index_dictionary[$SwitchAreas/Switch3/Sprite.texture])
	# Call a method to destroy the colliders in this scene to prevent hitting two items or hit the same twice
	_destroy_items_collision()
	pass 

# Method to destroy the item colliders
func _destroy_items_collision():
	$SwitchAreas/Switch1/CollisionShape2D.queue_free()
	$SwitchAreas/Switch2/CollisionShape2D.queue_free()
	$SwitchAreas/Switch3/CollisionShape2D.queue_free()
	pass

# Destroys this scenario when it exits the screen
func _on_VisibilityNotifier2D_screen_exited():
	self.queue_free()
	pass

The main game scene tree:

Player script (without the movement code):

extends KinematicBody2D

# Preloading player animations in different colors
var red = preload('res://animations/player_red.tres')
var green = preload('res://animations/player_green.tres')
var purple = preload('res://animations/player_purple.tres')
var black = preload('res://animations/player_black.tres')

# Storing the player animations in an anrray in the same order of the dictionary in scenario script
var colors = [green, red, purple, black]

func _ready():
	set_process_input(true)
	pass

func _physics_process(delta):
	# Method to check if a new scenario must be spawned
	_authorize_new_scenario()

# Variable to determine the distance the player must be to spawn the first scenario
var distance = 1100
# Signal to authorize a new scenario spawn
signal add_scenario

# To be called when player position is greater than distance variable, and increment variable to keep spawning
func _authorize_new_scenario():
	if position.x >= distance:
		distance += 1024
		emit_signal("add_scenario")
		pass
	pass

# Method called by the collision signal to change player color to the same as the item he collided with
func _get_skin_index(index):
	print("signal received")
	if index == null:
		print('just smile baby')
	else:
		$switch_skin_sound.play()
		print(index)
		$AnimatedSprite.frames = colors[index]
	pass

Sorry for the amount of information and for my english (if it sucked), just been trying to find the problem behind this for last 3 days and don’t know what to do anymore. :S

I can’t quite pinpoint the problem here. Maybe there’s a problem in the _destroy_items_collision() function? Maybe it’s removing the collisions necessary to trigger the signal?

Ertain | 2019-10-08 19:52

i figured out :smiley:

thanks for the answer, the problem was that the signal was only connecting when a collision occurred, i just connected it on _ready method in the main game script ^^

FelipeRattu | 2019-10-09 10:31