Building a Scene to Instance in Code

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

I have a giant database full of “bullet data.”

Bullets can have all sorts of shapes, use all sorts of frames, and so on.

I want to take advantage of Godot’s instance() mechanic as much as I can.

I know that I can instance a ‘base’ scene (like “bare_bones_bullet.tscn”), and then create other nodes (like adding the Area2D nodes and AudioStreamPlayers).

But it seems like I should be able to “build” a scene that I wish to instance with the data.

So I could make one character’s bullets, set all the variables, and then instance that already-fleshed-out bullet, instead of building it / assembling it every time a base scene is instanced.

Is this something that I can do in Godot? Or do I just have to re-build a bullet every time it is instanced?

:bust_in_silhouette: Reply From: ponponyaya

Sure you can do this in Godot.

For example, you can create an initialized function to do that, and runs the function when you instance the bullet scene. Then everytime you
can instance different bullet scene(base on pass different values to the initialized function)

The Following codes just an idea(and you have to let the initialized function work by writedown more codes):

[In bullet.gd]

var bullet_atk:int # bullet's attack power
var bullet_damage_range:int # bullet's damage range 
var bullet_speed:int # bullet's shoot speed
var bullet_img:String # bullet's sprite texture path

func initial_bullet(atk:int, drange:int, speed:int, img:String):
	bullet_atk = atk
	bullet_damage_range = drange
	bullet_speed = speed
	bullet_img = img
	......# do what you want to do

—Update following—
You can use sprite to create CollisionPolygon2D in code. Like the following:

var loadimg = Image.new()
loadimg.load("your_img_path")
var bitmap = BitMap.new()
bitmap.create_from_image_alpha(loadimg)

var polygons = bitmap.opaque_to_polygons(Rect2(Vector2(0,0), bitmap.get_size()))

for polygon in polygons:
	var collider = CollisionPolygon2D.new()
	collider.polygon = polygon
	call_deferred("add_child", collider)
	collider.position = $Sprite.position

—New update—

Use function call_deferred is for safe.
If you really care timer, you can try using multiple threads.

Unfortunately, this does not address the initial question.
I know I can change ints, floats, &c after instancing.

But I am wanting to attach completely different nodes to these things.
For instance, I want to attach a CollisionShape2D to an Area2D inside the bullet.

With this method, I would have to tell the Area2D to add_child(CollisionShape2D) after instancing it. But I want to “build” the whole bullet with all its nodes already “in place” so I can call the already-modified instance, and not have to instance/modify several times a second (in the case of rapid fire).

jerryjrowe | 2022-03-31 20:14

You can use sprite to create CollisionPolygon2D in code. Like the example I updated in answer.

ponponyaya | 2022-04-01 00:07

It’s this “call deferred” that seems to be messing with me.
It’s a delay.

A delay that wouldn’t be there with just a simple .instance()

It’s messing with my timers, it seems, when I have to wait on all the attaching / deferring.

jerryjrowe | 2022-04-01 05:42

Use function call_deferred is for safe.
If you really care timer, you can try using multiple threads.

ponponyaya | 2022-04-01 08:25

:bust_in_silhouette: Reply From: Gollum

I am a beginner in Godot. Menham makes extensive use of this instance () property. So far I have used it a lot and found it very convenient. Depending on the purpose of the program, I have sometimes seen problems.

:bust_in_silhouette: Reply From: omggomb

If your database doesn’t change during the game, you could try creating a tool script (script that runs in editor) which reads the database, constructs scenes for all bullet variations and then saves those to disk.

If you database changes, you could create your scene hierarchy for each variation once, store it in a var and the just deep duplicate that node whenever you need it. As long as you don’t add your original node to the scene tree it won’t take up much resources. Though you need to take care of not sharing state between the original and duplicated nodes, of course. Scenes are nothing more but predefined node hierarchies, so this is basically the same as using scenes.