How to limit the number of mobs being spawned?

Godot Version

4

Question

Basically my mobs are spawning too quickly and there’s way to many of them.

extends Node

@export var mob_scene: PackedScene
var score

func _ready():
	new_game()

func game_over():
	$MobTimer.stop()

func new_game():
	$Player.position = $StartPosition.position
	$StartTimer.start()
	$MobTimer.start()

func _on_start_timer_timeout():
	print ("timer good")
	
	

func _on_mob_timer_timeout() -> void:
	print("mob timer triggered")
	var mob = mob_scene.instantiate()
	print ("mob instantiated and added")
	var mob_spawn_location = $MobPath/MobSpawnLocation
	mob_spawn_location.progress_ratio = randf()

	# Set the mob's direction perpendicular to the path direction.
	var direction = mob_spawn_location.rotation + PI / 2

	# Set the mob's position to a random location.
	mob.position = mob_spawn_location.position

	# Add some randomness to the direction.
	direction += randf_range(-PI / 4, PI / 4)
	mob.rotation = direction

	# Choose the velocity for the mob.
	var velocity = Vector2(randf_range(100,100), 0.0)
	mob.linear_velocity = velocity.rotated(direction)

	# Spawn the mob by adding it to the Main scene.
	add_child(mob)
	
# Variables to track spawning
var max_mobs = 10  # Maximum number of mobs allowed
var current_mobs = 0  # Counter for how many mobs have been spawned

# Function to spawn a new mob
func spawn_mob():
	if current_mobs < max_mobs:
		current_mobs += 1  # Increase the spawn counter
	else:
		print("max number!!")
1 Like

You could call $MobTimer.stop() when max_mobs is reached.

var max_mobs = 10 
var current_mobs = 0  # Counter for how many mobs have been spawned

# Function to spawn a new mob
func spawn_mob():
	if current_mobs < max_mobs:
		current_mobs +=1  # Increase the spawn counter
		$MobTimer.stop()

	else:
		print("max number!!")
func remove_mob(mob):
	mob.queue_free()  # Removes the mob from the scene
	current_mobs -= 1  # Decrease the mob count
	print("Mob removed! Current mobs: ", current_mobs)

this what I’ve changed but it still doesn’t do anything

Make sure spawn_mob() is called. Also, make sure that’s where $MobTimer.stop() should be called.

can you show that would look like? I’m still very new at this sorry

1 Like

Follow the logic of your code and double check if everything makes sense where its at. Be mindful of the indentations. Just like what @indicainkwell said.

Reply clean up.(Hidden but kept)

THIS INFORMATION MAY BE WRONG, INACCURATE, MISLEADING. USE WITH CAUTION.

Below, I made one change. It may not be correct so, keep that in mind. I assumed that $MobTimer.stop() controls the spawn rate. when stopped, mobs no longer spawns.

It can get messy but, I personally like to add comments/print() with debug messages to help track, visualize among other things for the code logic.
There are other print() functions that does other things like printing to the debugger.

var max_mobs = 10 # I recommend adding more control to these variables to ensure that current_mobs don't exceed max_mobs. Like a range/max/clamp, what ever it is for godot. The godot manual is your best friend.
var current_mobs = 0 

# Function to spawn a new mob
func spawn_mob():
	if current_mobs < max_mobs: # keep spawning mobs until max limit is reached
		current_mobs +=1 
# It might be better to put your mob spawn code here or move this function to where the code to spawn mobs is at...or any of the other ways of doing it. Keeping related code together makes it cleaner as well as other benefits.

	else: # max limit is reached, stop spawning mobs.
$MobTimer.stop()
		print("max number!!")
func remove_mob(mob): # Depending where/when this is called as well as the $MobTimer.start() and spawn_mob(), the mobs will immediately start spawning again.
	mob.queue_free()
	current_mobs -= 1
	print("Mob removed! Current mobs: ", current_mobs)

After Additional Review

  • Double check the given time that the timer has.
  • $MobTimer.stop() may be used wrong, used at wrong time, etc.
  • Each time $MobTimer.stop() is used, _on_mob_timer_timeout may be inadvertently triggered. This will spawn a mob, each and every time. There might be no check to ensure that a mob should or shouldn’t be spawned.
  • Is the timer being reset back to it’s full timer or is it continuing from where it was left off when it was stop()? It could be double triggering _on_mob_timer_timeout …Bypassing any checks you may have like the “if current_mobs < max_mobs:” resulting in more spawns than intended…$MobTimer.stop() spawns mob then $MobTimer continues to count down resulting in another spawn. < – This is my #1 guess. May not be 100% accurate or true…Definitely worth looking at your timer and double checking it.

Pseudo Code

  • Here is a code snippet that might be worth looking at. Be mindful of the indentations. I couldn’t add in the proper indentations.
var mob_spawning = false

if current_mobs < max_mobs:
mob_spawning = true
# Enable the timer to continue counting down here
else:
mob_spawning = false
# Disable the timer from counting down here


func _on_mob_timer_timeout() -> void: # When timer timesout, attempt to spawn mobs
	if mob_spawning : # mob spawning is allowed.
# Add in the code that creates/spawns in the mob
		current_mobs += 1  # Increase the spawn counter
print("Spawning Mob")
	else: # mob spawning is not allowed
$MobTimer.stop() # Stop timer. DONT FORGET TO RESET THE TIMER. Timer continues where it left off.
		print("Mob Spawning disabled")

Hope this gets you back on track. Do apologize about the mess.

If all else fails, restart from scratch. Working out the logic, one step at a time.

1 Like

this seems to be helpful so far but it says current_mobs isn’t declared

If you’re copy n pasting the pseudo code I gave, you’ll have to ensure the integrity of it. Indentation, variable declaration, etc. is missing.

If all else fails, restart from scratch. Working out the logic, one step at a time.

Also note, that the pseudo code may not be the ideal way of doing that but should be used as a guide to get you back on track.

Make some more attempts at your code and let us know how it’s going.

1 Like
extends Node

@export var mob_scene: PackedScene
@export var max_mobs: int = 10
var score

#An array that contains all your spawned mobs------
var mobs_list = []

func _ready():
	new_game()

func game_over():
	$MobTimer.stop()

func new_game():
	$Player.position = $StartPosition.position
	$StartTimer.start()
	$MobTimer.start()

func _on_start_timer_timeout():
	print ("timer good")

func _on_mob_timer_timeout() -> void:
      If mobs_list.size() < max_mobs:
	print("mob timer triggered")
	var mob = mob_scene.instantiate()
	print ("mob instantiated and added")
	var mob_spawn_location = $MobPath/MobSpawnLocation
	mob_spawn_location.progress_ratio = randf()

	# Set the mob's direction perpendicular to the path direction.
	var direction = mob_spawn_location.rotation + PI / 2

	# Set the mob's position to a random location.
	mob.position = mob_spawn_location.position

	# Add some randomness to the direction.
	direction += randf_range(-PI / 4, PI / 4)
	mob.rotation = direction

	# Choose the velocity for the mob.
	var velocity = Vector2(randf_range(100,100), 0.0)
	mob.linear_velocity = velocity.rotated(direction)

	# Spawn the mob by adding it to the Main scene.
	add_child(mob)

        #Add the mob to mob_list-----------------------------
	mob_list.append(mob)


#This function is not necessary for me --------------------IMO
# Function to spawn a new mob
func spawn_mob():
	if current_mobs < max_mobs:
		current_mobs += 1  # Increase the spawn counter
	else:
		print("max number!!")

#--------------------------------------
#When a mob is dead should be erased from mob_list so a new #one can spawn 

func remove_mob(mob):
 mob_list.erase(mob)

#------------------------------------------
###On the mob's script at the take damage code 
###or dead code :slight_smile: 
get_parent().remove_mob(self)

#the mob is added as a child of "Node" in spawn function so #we're calling parent remove_mob function in our mob scene

Am new in gdscript but also in English, so I hope you can understand my bad grammar… Let me know if it’s works for you :sunglasses::+1: