How to create multiple instances with specific traits from an Object/Scene and add them to my main Scene?

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

I have 3 types of Buildings. I want to create let’s say 20 of them, at random, with their translate also random. I’m trying this code, but I think it overrides each one witht the latest one:

extends Spatial
onready var scenaryPlaneDims = get_node("Floor").scale

var building1Instance = preload("res://Buildings/Building1.tscn").instance()
var building2Instance = preload("res://Buildings/Building2.tscn").instance()
var building3Instance = preload("res://Buildings/Building3.tscn").instance()

# Called when the node enters the scene tree for the first time.
func _ready():
	randomize()
	for n in 20:
		call_deferred("add_building_to_root", building1Instance)
		call_deferred("add_building_to_root", building2Instance)
		call_deferred("add_building_to_root", building3Instance)


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


func add_building_to_root(instance):
	get_tree().get_root().add_child(instance)
	instance.set_translation(Vector3(randi()%50,0,randi()%50))
	#instance.set_scale(Vector3(100,100,100))
 

How can I create individual instances of those Buildings with specific attributes?

Just set those attributes?
Or what did you mean?

sash-rc | 2022-01-29 21:23

The attributes I mean are mainly translate, to position each instance at a random translate (in 3D obvs).

animanoir | 2022-01-29 22:31

Posted as an answer

sash-rc | 2022-01-30 10:35

:bust_in_silhouette: Reply From: sash-rc

Well, in addition to some minor issues like

  • global randomize() should be called only once (I’m not sure this is so) in project, preferably in autoload-nodes, or RandomNumberGenerator class instance should be used.
  • you’re adding Spatial-based (are they?) node as a child of root (Viewport), while normally it’s better to add it to another Spatial-based node like floor/ground (in its _ready()), thus you don’t have to use call_deferred().
  • you’re feeding integer values of randi() to a float Vector3 (should be randf(), or rand_range())
  • your overall generation algorithm: it does not guarantee you won’t get overlapping results.

you have only 3 instances, which you’re translating 20 times. You should move instance() under for loop:

var packedScene1  = preload("res://Buildings/Building1.tscn") 
# ...

for n in 20:
    var building =  packedScene1.instance()
    $someNode.add_child(building)
    building.set_translation(...)

Thanks. I’m new to Godot in general so thanks for noticing those minor issues. Lemme try your answer.

animanoir | 2022-01-31 01:29