Signal not propagating to connected Object

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

I’m designing a modular map generator. Generators derive from object and have an array of Module objects (also derive from object). A single Node2D (Gen2Testing) with a TileMap child owns the Generator object. RIght now I only have 1 module, DefaultTerrainModule which only listens for the generate_map signal from Gen2Testing. This signal passes a Vector2, dimension, and a reference to the TileMap.

On Gen2Testing’s _ready(), I .connect("generate_map", module, "_generate", [dimension, tile_map])) for every Module object stored in the Generator (which at the moment initializes with a lone DefaultTerrainModule) The error code is 0, and if I check the connection with is_connected('generate_map', module, '_generate'), I get True.

When I actually try sending the signal though, no code in the Module’s _generate() function ever gets called. Any advice?

Here’s the code:
Gen2Testing.gd (attached to Gen2Testing: Node2D, the scene root, parent of a TileMap):

extends Node2D

signal generate_map(dimension, tile_map);

export (Vector2) var dimension = Vector2(100, 100);

var generator: Gen2 = Gen2.new();

onready var tile_map = $TileMap;

func _ready() -> void:
	connect_generate_map_signal();

func _process(_delta: float) -> void:
	if (Input.is_action_just_pressed("f1")):
		connect_generate_map_signal();
	
	if (Input.is_action_just_pressed("f2")):
		print("sending signal")
		emit_signal("generate_map", dimension, tile_map);
	
	if (Input.is_action_just_pressed("f3")):
		print(generator.modules)

func connect_generate_map_signal() -> void:
	print(generator.modules)
	for module in generator.modules:
		print(module.name)
		var er: = connect("generate_map", module, "_generate", [dimension, tile_map]);
		print("connecting {self} to {module}. Error code: {er} ".format(
				{"self":self, "module": module, "er":er}))
		print("is_connected('generate_map', module, '_generate'): " + 
				str(is_connected('generate_map', module, '_generate')))

Gen2.gd:

extends Object
class_name Gen2

var modules:Array = [];

func _init():
	modules.append(DefaultTerrainModule.new())

Gen2Module.gd (not really relevant, just including in case!):

extends Object

func generate():
	print("You were supposed to override this!")

DefaultTerrainModule.gd:

extends "res://2D PoC/Gen2/Scripts/Gen2Module.gd"
class_name DefaultTerrainModule

var name = "named module1"

func _generate(dim: Vector2, tm: TileMap):
	print("signal received from " + str(get_instance_id()));
:bust_in_silhouette: Reply From: DDoop

This video at about 4:00 explained the issue. When using the binds parameter in connect(), those variables will always be emitted, even if you don’t say so when you emit the signal. So don’t include those parameters when you emit them, if you went through the trouble to make a binding.
Honestly I don’t understand why removing the parameters from my emit_signal() fixed it, but that’s what fixed it. Maybe when you add parameters to a signal with parameters that have been binded with connect(), you actually pass them twice so Godot was looking for a signature with 4 parameters. Regardless, I can’t test this by adding a corresponding _generate() function in DefaultTerrainModule because Godot complains that it doesn’t match the Variant it’s expecting (with 2 parameters)

Further investigation confirms the video’s statement that connection bindings are also constant. I.E., reassigning dimension.x to a new int value, or assigning dimension to a new Vector2 will not result in those changed values being passed in the signal. This is because I passed those values/reference (the TileMap as well) in as bind arguments when the connection was made.

This is not clearly stated in the function’s documentation here.

DDoop | 2020-12-13 19:22