How to connect a signal to an instanced scene

Godot Version

4.2

Question

I have a battle scene and an enemy scene that gets instantiated inside the battle scene.

The enemy scene has a target marker that is hidden by default.
My goal is to make the marker pop up (show itself) whenever the player hovers over the enemy with their mouse cursor and hide itself, when the cursor exited.

Here’s enemy script:

extends Area2D

@onready var target_marker = $TargetMarker



func _on_mouse_entered():
	emit_signal("mouse_entered")
	target_marker.show()


func _on_mouse_exited():
	emit_signal("mouse_exited")
	target_marker.hide()

And here’s battle scene script:

extends Node2D

@onready var pos1 = $Position1
@onready var pos2 = $Position2
@onready var pos3 = $Position3
@onready var pos4 = $Position4
@onready var pos5 = $Position5

var wooddog_PLOAD = preload("res://scenes/characters/enemies/wooden_doggo.tscn")
var watersprite_PLOAD = preload("res://scenes/characters/enemies/water_sprite.tscn")
var mushroom_PLOAD = preload("res://scenes/characters/enemies/mushroom.tscn")
var bikini_PLOAD = preload("res://scenes/characters/enemies/bikini.tscn")

var enemy_num = [1, 2, 3, 4]
var enemies = [
	wooddog_PLOAD, 
	wooddog_PLOAD, 
	wooddog_PLOAD, 
	wooddog_PLOAD, 
	wooddog_PLOAD, 
	watersprite_PLOAD, 
	watersprite_PLOAD, 
	watersprite_PLOAD, 
	mushroom_PLOAD, 
	mushroom_PLOAD, 
	mushroom_PLOAD, 
	bikini_PLOAD
]
var positions = [pos1, pos2, pos3, pos4]
var enemy_group = []
var pos1_taken = false
var pos2_taken = false
var pos3_taken = false
var pos4_taken = false

# Called when the node enters the scene tree for the first time.
func _ready():
	for enemy in range(enemy_num.pick_random()):
		enemy_group.append(enemies.pick_random())
	for enemy in enemy_group:
		if enemy == wooddog_PLOAD:
			var wooddog_ins = wooddog_PLOAD.instantiate()
			if pos1_taken == false:
				wooddog_ins.global_position = pos1.global_position
				pos1_taken = true
			elif pos2_taken == false:
				wooddog_ins.global_position = pos2.global_position
				pos2_taken = true
			elif pos3_taken == false:
				wooddog_ins.global_position = pos3.global_position
				pos3_taken = true
			else:
				wooddog_ins.global_position = pos4.global_position
				pos4_taken = true
			add_child(wooddog_ins)
# Here's my dead attempt at connecting the signal after 1000000th time of trying
			wooddog_ins.connect("mouse_entered", _on_mouse_entered)
		elif enemy == watersprite_PLOAD:
			var watersprite_ins = watersprite_PLOAD.instantiate()
			if pos1_taken == false:
				watersprite_ins.global_position = pos1.global_position
				pos1_taken = true
			elif pos2_taken == false:
				watersprite_ins.global_position = pos2.global_position
				pos2_taken = true
			elif pos3_taken == false:
				watersprite_ins.global_position = pos3.global_position
				pos3_taken = true
			else:
				watersprite_ins.global_position = pos4.global_position
				pos4_taken = true
			add_child(watersprite_ins)
		elif enemy == mushroom_PLOAD:
			var mushroom_ins = mushroom_PLOAD.instantiate()
			if pos1_taken == false:
				mushroom_ins.global_position = pos1.global_position
				pos1_taken = true
			elif pos2_taken == false:
				mushroom_ins.global_position = pos2.global_position
				pos2_taken = true
			elif pos3_taken == false:
				mushroom_ins.global_position = pos3.global_position
				pos3_taken = true
			else:
				mushroom_ins.global_position = pos4.global_position
				pos4_taken = true
			add_child(mushroom_ins)
		else:
			var bikini_ins = bikini_PLOAD.instantiate()
			if pos1_taken == false:
				bikini_ins.global_position = pos1.global_position
				pos1_taken = true
			elif pos2_taken == false:
				bikini_ins.global_position = pos2.global_position
				pos2_taken = true
			elif pos3_taken == false:
				bikini_ins.global_position = pos3.global_position
				pos3_taken = true
			else:
				bikini_ins.global_position = pos4.global_position
				pos4_taken = true
			add_child(bikini_ins)
	

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	pass

(I left a comment above the line where I tried to connect the signal)
What am I doing wrong?
I’ve watched tons of videos. I’ve looked in the godot docs. I’ve looked here…
…nothing

Are you wanting to connect your mouse_entered to wooddog_ins or its signal to itself, or to something else?

If wooddog_ins is using the first script then just use:

wooddog_ins.connect("mouse_entered", wooddog_ins._on_mouse_entered)

Though better code would be:

wooddog_ins.mouse_entered.connect(wooddog_ins._on_mouse_entered)

But you can just connect that signal when you create that scene already with the connections dialog, see here

Well, to be honest I don’t know. When I connect enemy’s signal to itself and then open the enemy scene, then the target marker pops up and disappears the way I wanted to, but when I spawn the enemy in the battle scene the marker doesnt pop up, so I assumed I needed to connect enemy’s signal with the battle scene.

I’m trying to learn how signals work.

That should work, assuming you connect it in the editor and save the scene correctly, if it is a signal on itself to itself :slight_smile:

I tried both of those and they dont work…

Can you please show the scene file of that? The tscn file? res://scenes/characters/enemies/wooden_doggo.tscn, just so I can see how it’s configured?

Ofcourse, I’m not entirely sure how, but I’ll do my best!

Here, I hope this helps:

It isn’t connected there, see to the right? mouse_entered? Connect it and the other signal :slight_smile:

Done, but it still doesn’t work and when I open the enemy scene and hover over the enemy, the game crashes and I get this error:

Oh that’s because the mouse exits when it’s hidden, and then shown, and then hidden, infinitely

You need to handle this differently, unsure exactly how so that’s something you need to work out for your speicific case

1 Like

Oh okay, I’ll try to do that then. Thank you so much for the help and quick response! :sparkling_heart:

1 Like

Thank you for a nice exchange :orange_heart: good luck!

1 Like

There’s only two levels here

I count 3 and then 5 under each one, its making my head hurt just looking at it.

:rofl:

Actually its 4 and then 4 under each one including the last else statement!

There’s two, the others are a function and a for statement

First statement, 4 IF conditions

if enemy == wooddog_PLOAD:

Second statement, 4 IF conditions

ekif enemy == watersprite_PLOAD:

and so on … .

So you are testing against 4 conditions, and then one of those has 4 conditions under it. For every enemy in the group so I hope there isnt a lot of them!

Its not very efficient as if your object is bikini and is pos4 its got to evaluate 4 conditions and then another 4 conditions on top of that to get to that point.

At the very least use a match statement for the pos checking to make the code more readable.

Dude, I’m making a “simple” jrpg battle scene with 4 enemies on the screen max.

I know this code isn’t perfect, but everything worked well until I hit a wall.
I was planning to improve it, but I wanted to make a target indicator on hover first.
In theory, it’s nothing too complicated.

My knowledge of GDscript ends with these two guides:
https://www.youtube.com/watch?v=-VFOwJXpQi8&list=PLNCitZ2dgQpYWbMdT6ai5Z4apg7_ShydQ
https://www.youtube.com/watch?v=HEexLmt7enc
and some random stuff I found in Godot docs and on youtube.
So I have no idea what you’re talking about.

I don’t know how to solve my issue, so now I’m stuck reading comments of a guy who’s spamming under my post about things nobody asked for.

1 Like