These Timers have been driving me genuinely crazy, I'm one single step from finally being done with this Timer system!

Godot Version

4.7.1.stable

Question

I have spent maybe just under week trying to get this enemy spawning timer to work whenever the level changes. The levels all have the same script because they have to all be the same.

I will have the room code and player code linked below, aswell as the enemy code and door code.

The goal is for when you enter a door and the lvel changes(this part works), the enemies should start the spawning code(which works when activated).

#DoorCode

extends Area2D

signal startLVL

func _ready():
	$GreyDoor.play("Closed")


func _on_body_entered(body: Node2D) -> void:
	if body.is_in_group("Romeo"):
		# var current_scene_file = get_tree().current_scene.scene_file_path
		var next_level_number = randi_range(1, 2)
		
		var next_level_path = "res://Scenes/Levels/Room" + str(next_level_number) + ".tscn"
		get_tree().change_scene_to_file(next_level_path)
		
		emit_signal("startLVL")
		print("Sent")

#Room/LVLcode

extends Node2D


var enemiesLeft = 0
@export var enemy_new: PackedScene = preload("res://Scenes/HappyEnemy.tscn")


func _ready() -> void:
	var spawn_point = %Spawnpoint1
	var door = $Doors/DoorNode/DoorGrey
	var door2 = $Doors/DoorNode2/DoorGrey
	var door3 = $Doors/DoorNode3/DoorGrey
	var door4 = $Doors/DoorNode4/DoorGrey

	
	door.startLVL.connect(_on_door_grey_start_lvl)
	door2.startLVL.connect(_on_door_grey_start_lvl)
	door3.startLVL.connect(_on_door_grey_start_lvl)
	door4.startLVL.connect(_on_door_grey_start_lvl)
	
	LVLentered()


func _process(delta: float) -> void:
	if enemiesLeft > 0:
		$Doors/DoorNode/DoorGrey/GreyDoor.play("Closed")
		$Doors/DoorNode2/DoorGrey/GreyDoor.play("Closed")
		$Doors/DoorNode3/DoorGrey/GreyDoor.play("Closed")
		$Doors/DoorNode4/DoorGrey/GreyDoor.play("Closed")
		
		$Doors/DoorNode/DoorGrey/StaticBody2D.set_collision_layer_value(2,true)
		$Doors/DoorNode/DoorGrey/StaticBody2D.set_collision_layer_value(3,true)
		
		$Doors/DoorNode2/DoorGrey/StaticBody2D.set_collision_layer_value(2,true)
		$Doors/DoorNode2/DoorGrey/StaticBody2D.set_collision_layer_value(3,true)
		
		$Doors/DoorNode3/DoorGrey/StaticBody2D.set_collision_layer_value(2,true)
		$Doors/DoorNode3/DoorGrey/StaticBody2D.set_collision_layer_value(3,true)
		
		$Doors/DoorNode4/DoorGrey/StaticBody2D.set_collision_layer_value(2,true)
		$Doors/DoorNode4/DoorGrey/StaticBody2D.set_collision_layer_value(3,true)
		
	
	else:
		$Doors/DoorNode/DoorGrey/GreyDoor.play("Opened")
		$Doors/DoorNode2/DoorGrey/GreyDoor.play("Opened")
		$Doors/DoorNode3/DoorGrey/GreyDoor.play("Opened")
		$Doors/DoorNode4/DoorGrey/GreyDoor.play("Opened")
		
		$Doors/DoorNode/DoorGrey/StaticBody2D.set_collision_layer_value(2,false)
		$Doors/DoorNode/DoorGrey/StaticBody2D.set_collision_layer_value(3,false)

		$Doors/DoorNode2/DoorGrey/StaticBody2D.set_collision_layer_value(2,false)
		$Doors/DoorNode2/DoorGrey/StaticBody2D.set_collision_layer_value(3,false)

		$Doors/DoorNode3/DoorGrey/StaticBody2D.set_collision_layer_value(2,false)
		$Doors/DoorNode3/DoorGrey/StaticBody2D.set_collision_layer_value(3,false)

		$Doors/DoorNode4/DoorGrey/StaticBody2D.set_collision_layer_value(2,false)
		$Doors/DoorNode4/DoorGrey/StaticBody2D.set_collision_layer_value(3,false)


func LVLentered():
	print("STARHHHHHHHTED")
	$Essentials/SpawnTimer.start()
	$Essentials/SpawnTimer/SpawnRate.start()

func spawn_enemy():
	var enemy_temp = enemy_new.instantiate()
	add_child(enemy_temp)
	enemy_temp.position = $Essentials/Spawnpoint1.global_position
	enemiesLeft += 1
	print(enemiesLeft)

	var romeo = $Essentials/RomeoBody
	romeo.selfLocate.connect(enemy_temp._on_romeo_body_self_locate)
#	romeo.resendDMGOutput.connect(enemy_temp._on_romeo_body_resend_dmg_output)
	enemy_temp.DMGRomeo.connect(romeo._on_happy_enemy_dmg_romeo)
	romeo.tellDMG.connect(enemy_temp._on_romeo_body_tell_dmg)
	enemy_temp.enemyDied.connect(_on_happy_enemy_enemy_died)

#	if enemiesLeft  1


func _on_spawn_timer_timeout() -> void:
	print("TIEM")
	$Essentials/SpawnTimer.stop()
	$Essentials/SpawnTimer/SpawnRate.stop()

func _on_spawn_rate_timeout() -> void:
	spawn_enemy()
	$Essentials/SpawnTimer/SpawnRate.wait_time = randi_range(0,3)


func _on_happy_enemy_enemy_died() -> void:
	enemiesLeft -= 1
	print(enemiesLeft)


func _on_door_grey_start_lvl() -> void:
	LVLentered()

#PlayerCode

extends CharacterBody2D

signal tellDMG(value)
signal selfLocate(value)
signal updateHP(value)
#signal resendDMGOutput(value)

var SANITY = 30
var HP = 30
var WRATH = DMG 
var DMG = 5
var rangedDMG = DMG
var GREED = LUCK 
var LUCK = 0
var SLOTH = SPD
@export var SPD : float = 100
var PRIDE = ARMR
var ARMR = 0
var GLUTTONY = MLTP 
var MLTP = 0.0
var LUST = CD 
var CD = 0.0
@onready var animated_sprite = $RomeoSprite


func _physics_process(_delta):
	var character_direction = Input.get_vector("Move_Left","Move_Right","Move_Down","Move_Up")
	velocity = character_direction * SPD
	move_and_slide()

	emit_signal("selfLocate",position)

	if HP < 1:
		get_tree().reload_current_scene()

	#VariablesGlb.romeosDMG = DMG
	#print(VariablesGlb.romeosDMG)
	emit_signal("tellDMG",DMG)


#func _on_happy_enemy_output_recieve_dmg() -> void:
#	emit_signal("resendDMGOutput",DMG)


func _on_heart_body_entered(body: Node2D) -> void:
	if body.is_in_group("Romeo"):
		emit_signal("dmgEnemy",rangedDMG)
		print("hhhhhh")


func _on_heart_holder_play_shooting() -> void:
	$RomeoSprite.play("Shooting")


func _on_heart_holder_play_shot() -> void:
	$RomeoSprite.play("Shot")


func _on_romeo_sprite_animation_finished() -> void:
	$RomeoSprite.play("Idle")





func _on_happy_enemy_dmg_romeo(value: Variant) -> void:
	$RomeoSprite.play("Injured")
	HP -= value
	emit_signal("updateHP",value)

#EnemyCode

extends CharacterBody2D

signal DMGRomeo(value)
signal enemyDied

var romeoDMG = 0
var HP = 10
var DMG = 5
var SPD = 40.0
var LUCK = 0
var player_pos
var target_pos
#@onready var player = get_parent().get_node("RomeoBody")


func _on_romeo_body_self_locate(value: Variant) -> void:
	player_pos = value
	target_pos = (player_pos - position).normalized()

	if position.distance_to(player_pos) > 1:
		velocity = target_pos * SPD
		move_and_slide()

func _physics_process(_delta):
	#player_pos = RomeoLocation.global_position

		

	if HP < 1:
		SPD = 0
		$AnimatedSprite2D.play("Death")
		emit_signal("enemyDied")
		queue_free()

func _on_atkzone_body_entered(_body: Node2D) -> void:
	$Swing.visible = true
	get_node("Swing/AnimatedSprite2D").play("Swing")

func _on_atkzone_body_exited(_body: Node2D) -> void:
	$Swing.visible = false

func _on_swing_body_entered(body: Node2D) -> void:
	if body.is_in_group("Romeo"):
		emit_signal("DMGRomeo",DMG)


func _on_romeo_body_resend_dmg_output(value: Variant) -> void:
	HP -= value
	$AnimatedSprite2D.play("Hurt")


func _on_animated_sprite_2d_animation_finished() -> void:
	$AnimatedSprite2D.play("Normal")


func _on_romeo_body_tell_dmg(value: Variant) -> void:
	var _romeoDMG = value

func take_damage1():
	HP = HP - 5
	$AnimatedSprite2D.play("Hurt")

You forgot to describe how the actual problem manifests.

You enter the level and the timers don’t start

How did you determine that?

Because when I start the level it prints that the code is going through but the timers aren’t. Everything is working but the enemy spawning

What is printed? Do you have any errors or warnings?

What does it print? If it prints “STARHHHHHHHTED” and there are no errors reported then the timers are started. Their signals may not be correctly connected though.

Can I just say it’s difficult to read, we have no idea what you set on your timers as well. :slight_smile:

Is it one shot?

Autostart?

Where level starts? ( the code)

usually I connect on_timer_time_out in ready func, the best bet it’s working.

Room 1 works perfectly fine, and here are any errors+the tree. STARTH or wtv i called it does work, just not the timers

as you have autostart you can remove call for start(), and also print statement only means your func was called nothing else.

await get_tree().physics_frame

Add the line above here on the line before starting the timers. That makes you wait until next frame with starting them. They are probably not properly set up yet when you try to start thrm

I was thinking that, i’ll try and that rq

This did not work :frowning:

As the error message suggests - make a deferred call to change_scene_to_file(), instead of regular call.

What does this exactly mean?

It means you need to postpone (aka defer) the function call to after the frame has been processed. This is done using call_deferred(). So instead of:

get_tree().change_scene_to_file(next_level_path)

you do:

get_tree().call_deferred("change_scene_to_file", next_level_path)

or:

get_tree().change_scene_to_file.call_deferred(next_level_path)

This made the scene load properly but the enemies still don’t want to spawn, thus I still believe my timers are not working. Can you investigate my enemy code and room code? Mayhaps it’s in there?

You need to make sure that timer signals are properly connected.

IT WORKED! Thank you so much, i’m sorry I made it so difficult, first project