How do i spawn a certain number of enemies? and after i kill some of em, keep respawning

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

Hello. If anyone can help me with this problem, please. For the time being i’m using only one kind of enemy.
I tried to do it with an IF statement, i got the exact number of enemies that i required, but after one was killed they didn’t keep respawning. Also i would like to ask if it is appropiate to use this IF statement to control the number of spawned enemies. Thanks in advance.

extends Timer
var slime = preload("res://enemy/slime/Slime.tscn")
var count = 0
func _on_Timer_timeout():	
if count < 5:
	count += 1
	randomize()
	var enemies = [slime]
	var kinds = enemies[ randi()% enemies.size()]	
	var enemy = kinds.instance()
	enemy.position = Vector2(1083,rand_range(72,267))
	add_child(enemy)
	wait_time = rand_range(2,3)

are you decrementing count when an enemy is killed? if not, then that’s probably your problem.

godot_dev_ | 2023-06-21 22:54

:bust_in_silhouette: Reply From: jfran

I would like to update this case.
I managed to connect a signal that emits if the child node is added throught the editor, but this signal doesn’t emit if the child is added throught code.

I have 2 kinds of Slimes, one added throught the editor (it does emit the signal)
and the other spawns throught code (it doesn’t emit the signal)

Slime.gd:

signal enemy_killed
func _on_Stats_no_health():
	queue_free()
	emit_signal("enemy_killed")	

Slime Scene:
enter image description here

Here is my Timer that spawns Slimes:
Timer.gd:

extends Timer
var slime = preload("res://enemy/slime/Slime.tscn")
var count = 0

func _on_Timer_timeout():
	if count < 5:
		randomize()
		var enemies = [slime]
		var kinds = enemies[ randi()% enemies.size()]	
		var enemy = kinds.instance()
		enemy.position = Vector2(50,rand_range(72,267))
		add_child(enemy)
		wait_time = rand_range(2,3)
		count += 1

func _on_Slime_enemy_killed():
	print ("killed")

Spawner scene: (The Slime child scene was added throught editor, i did this way because i didn’t know how to emit a signal when the slime was killed.)
enter image description here

World scene: Slime A is generated throught the editor, cus it was instanced when i instanced Spawner, Slime B is spawned throught code in Timer.gd.
When A is killed it emits the signal killed in Slime.gd. but when B is killed it doesn’t emit the signal.

I don’t know to to make B to emit the signal, any ideas please?

enter image description here

I would try to solve your issue of not being able to connect functions to signal properly via nodes instance through code. I you can familiarize yourself with that, it may point out to you where all your bugs lie

(dynamically instancing nodes and adding them to the scene and connecting them to signals is important: if you avoid such designs your code will get messy)

This tutorial should help you with signals

godot_dev_ | 2023-06-22 15:29

:bust_in_silhouette: Reply From: godot_dev_

Here is an example of connecting a function to a signal emitted by a node dynamically added to the scene:

#parent  script
const CHILD_TYPE1_RESOURCE=preload("res://path/to/your/child1_scene.tscn")
const CHILD_TYPE2_RESOURCE=preload("res://path/to/your/child2_script.gd")
func _ready():
    var childT1Instance = CHILD_TYPE1_RESOURCE.instance()
    var childT2Instance = CHILD_TYPE2_RESOURCE.new()

    childT1Instance.connect("yoursignal",self,"_on_handle_signal",[childT1Instance])
    childT2Instance .connect("yoursignal",self,"_on_handle_signal")
    add_child(childT1Instance )
    add_child(childT2Instance )

func _on_handle_signal(child):
    pass#put your logic here

#a script attached to res://path/to/your/child1_scene.tscn"
signal yoursignal
func exampleFunction():
    emit_signal("yoursignal")


#a scene with res://path/to/your/child2_script.gd" attached
signal yoursignal
func exampleFunction():
    emit_signal("yoursignal",self) #we send a reference to the node itself to respect the fact _on_handle_signal expects a paramter (the child emitting the node)

Thanks for your time and help. your ideas gave me a general idea and managed to connect the signals, thank you again.

If anyone needs it, in the future, here is the solution.

After you instance an enemy, you have to connect the signal

func _on_Timer_timeout():
if count < 5:
    randomize()
    var enemies = [slime]
    var kinds = enemies[ randi()% enemies.size()]   
    var enemy = kinds.instance()

    connect_to_enemy_signals(enemy)  

    enemy.position = Vector2(50,rand_range(72,267))
    add_child(enemy)
    wait_time = rand_range(2,3)
    count += 1

Then create the func to the signal

func connect_to_enemy_signals(enemy: Slime): #Slime = Class_name
	var stats: Stats = enemy.get_node("Stats") #Stats = Class_name
	stats.connect("no_health", self, "on_Slime_Stats_killed")

func on_Slime_Stats_killed():
	print ("connected")

Note: i had to add class_names so the signals can be connected

class_name Slime #to the Slime scene
class_name Stats #to the child node Stats in Slime parent node

jfran | 2023-06-23 18:20