Instantiate CharacterBody3D to Random Spawn Points

Godot Version

Godot_v4.2.1-stable_win64

Question

Unsure why instantiated scene isn't being added.

I’m working on a scene where I’d like the instances of a Characterbody3D scene to be multiplied , so I tried by instantiating my scene stored in a preload variable (script below for context), and putting about five different spawn points represented by Node3D’s under another Node3D for organization purposes. I’ve tried unparenting them to see if the parent Node3D was getting in the way but that hasn’t worked. It is error free at the moment, but the print signal isn’t firing off that says there’s another instance, nor is there another instance to be seen. The last thing I’ve tried is trying to add a little less complexity by only choosing one of the spawn points and ignoring the rest, because it didn’t seem to work when I had an array of the spawn points.

func _on_plus_pressed():
		#Spawn Positions
		var SpawnPos = $Spawn1
		#Scene to Instance as child of Spawn (1-5, randomly)
		var MeatScene = preload("res://Meat/meat.tscn")
		var MeatInst = MeatScene.instantiate()
		for child in SpawnPos.get_children():
			#Choose random spawn to instance scene
			SpawnPos.add_child(MeatInst)
			#Checking for instance...
			if is_instance_valid(MeatInst):
				print("Another Meat spawned!")

Scene Tree and Viewport Reference :

Remote Debug and Debug Window (Lol ignore how cursed he looks) :

Scene that I want to Instance :

This adds MeatInst as a child to SpawnPos over and over again, 5 times, once for each child. You probably recieve errors for this. The for loop means it will iterate over each child, you don’t want to set the spawn point 5 times, you want to set it once by random.

You could pick a random child of SpawnPos like so

var random_spawn = SpawnPos.get_children().pick_random()
random_spawn.add_child(MeatInst)
2 Likes

Alright, I changed my script to the following, I also realized when I was putting my pick_random(), I put it at the front of the line. :sweat_smile:

After testing the script, I got this error when I pressed my button :

Invalid call. Nonexistent function 'get_children' in base 'Array'.

Is there a different way I need to put the Node3D’s into the array?

Here’s what I have now :

func _on_plus_pressed():
		#Spawn Positions
		var SpawnPos = [$Spawn1,$Spawn2,$Spawn3,$Spawn4,$Spawn5 ]
		#Scene to Instance as child of Spawn (1-5, randomly)
		var MeatScene = preload("res://Meat/meat.tscn")
		var MeatInst = MeatScene.instantiate()
		var Random_Spawn = SpawnPos.get_children().pick_random()
		Random_Spawn.add_child(MeatInst)
		#Checking for instance...
		if is_instance_valid(MeatInst):
			print("Another Meat spawned!")

SpawnPos is now an Array, which get_children() returns an Array, so we do not need get_children() anymore, and does not operate on Arrays themselves.

func _on_plus_pressed():
		#Spawn Positions
		var SpawnPos = [$Spawn1,$Spawn2,$Spawn3,$Spawn4,$Spawn5 ]
		#Scene to Instance as child of Spawn (1-5, randomly)
		var MeatScene = preload("res://Meat/meat.tscn")
		var MeatInst = MeatScene.instantiate()
		var Random_Spawn = SpawnPos.pick_random() # delete .get_children()
		Random_Spawn.add_child(MeatInst)
		#Checking for instance...
		if is_instance_valid(MeatInst):
			print("Another Meat spawned!")
2 Likes

Works perfectly, thank you for your help again!