Accessing a packed scene

Godot Version

v4.3.stable.official [77dcf97d8]

Question

Hi all,

I’m trying to figure out the best way to acces a packed scene to instantiate in the code. I know there are several ways and it depends on the situation.

In my case, I have two packed scenes that I may need to instantiate in potentially every node I have. I couldn’t figure out a neat way to do it. Right now, I feel like I have to do this in every node and select the scenes from Inspector. But I think there should be a better, centralized way to handle this.

@export var Scene1 : PackedScene
@export var Scene2 : PackedScene

EDIT: I should also note that these scenes are working as Custom Timer and Alarm in my game. So they are deleted once alarm/timer is off. And they are to be instantiated multiple times during the runtime. The nodes that needs to instantiate these packedscenes also be able to access them and change some variables (related to the duration of timer and alarm).

Thanks,

func Setup1s(Num:int=300,args:Array[Array]=[],kargs:Dictionary={})->bool:
	var N : Node = Node.new()
	N.name="S1s"
	add_child(N)
	for i in Num:
		var S1 : = Scene1.instantiate()
		if args!=[] or kargs!={}:
			S1.setup(args,kargs)
		N.add_child(S1)
	return true

Thank you @AlexanderLife but I really couldn’t understand what’s happening here. Can you explain if you don’t mind?

I come up with something like this, but I’m not sure if it’s a good implementation.

I have a ‘Globals’ script that is on Autoload and I add the scene there to acess from any script.
Only downside seems to be that I need to manually change the path of the packedscene if it is moved. But at least I’ll need to do this only in this global script.

(globals.gd → autoload with name Globals)

extends Node

var alarm_scene = preload(“res://05_tools/custom_alarm.tscn”)

func alarm():
var scene =alarm_scene.instantiate()
return scene

So I should be able to get a new instance of alarm in any other node with the code below:

var alarm_instance = Globals. alarm()
add_child(alarm_instance)

Any suggestion/comment would be really welcome.

Thanks

Hello, @lastbender! I think it’s normal way to do solution of your question. But I will extend your code:

extends Node

@export var preload_scenes: Array[PackedScene]

func get_alarm_scene():
     return preload_scenes[0].instantiate()

You can add all PackedScene to preload_scenes array at Inspector and get them by your get_some_scene functions by index of PackedScene at this array.

1 Like

For more script extends you can write enum for indexes of PackedScenes at your array. For example:

extends Node

enum ToolsScenes {SCENE_ALARM, SCENE_TIMRER}

@export var tools_scenes: Array[PackedScene]

func get_tool_scene(tool_scene: ToolsScenes):
     return tools_scenes[tool_scene].instantiate()

Then use:

# Some code...

func _ready():
    var alarm_scene_instance = Globals.get_tool_scene(ToolsScenes.SCENE_ALARM)
1 Like

I did not really get what you wanted by your first post, so I tried to write something that might be what you want. but I will go threw it to help you understand it.
so I saw you were using export to be able to load different scenes in the inspector.
@export var Scene1 : PackedScene
the Scene1 var could be filled with any scene
func Setup1s(Num:int=300,args:Array[Array]=[],kargs:Dictionary={})->bool:
is a function that is made to setup a number of Scene1.

so first I thought you might want a place to put all these Scene1 that will be set up.

var N : Node = Node.new()
N.name="S1s"
add_child(N)

var N : Node = Node.new() makes a new node to place all of the new Scene1 to be made N.name=“S1s” renames that node S1 for Scene1 then adds a s to imply their might be more then one Scene1 being organized. add_child(N) adds the organizer to what ever the script is in.
for i in Num:
is a loop that will run threw the intended section Num number of times. if we look up in the func part we see Num should be a int that’s a whole number because it’s hard to go threw a loop a 0.5 amount of times, num could be anything you need but we see the default amount for it to run threw this loop is 300 times a really large amount of times but I don’t know what you are doing. so I just wanted to expand your mind to possibilities and automation.
inside the for loop
var S1 : = Scene1.instantiate()
this makes object of the Scene1

so let’s say you have something that needs to be done with a new Scene1 that can’t really be done in the _ready() of Scene1
so like maybe this func Setup1s is inside of the NPCbaseclass but you have BobNPCclass and a AliceNPCclass that “copy and paste” the code of the func Setup1s from the NPCbaseclass by extends NPCbaseclass
but your Scene1 needs to know if it was made inside Bob or Alice.

func Setup1s( args:Array[Array]=[], kargs:Dictionary={}):
the args and kargs is something that can help you do this.
so say you make all of your Scene1 have a

var NPCName : String= "not known yet"
func setup(args:Array[Array]=[], kargs:Dictionary={}):
	NPCName=kargs["NPC_name"]
	NPCName=args[0][0]

when running func Setup1s( in bob you can do.

Setup1s	(	10,
			[["BobIsMyNameByArgs array"]],
			{"NPC_name":"BobIsMyNameByKargs Dictionary"},
		)

but it should only go down this rabbit hole if the args or the kargs is not empty.
if args!=[] or kargs!={}:
so != is not equal to
so args default setting is a
and kargs default setting is {}
so if it’s true that args is not the default or kargs is not the default then
S1.setup(args,kargs)
this is S1 the new Scene1 it should run it’s func setup.
and that func set up should be given the args and the kargs that contain the “bob” name.
ok so done setting up the new S1 but it’s floating in space
N.add_child(S1)
adds S1 to the N that is the place to organize the S1 Setup1s is making.
perhaps you need to know when all of the 300 Scene1 are set up and done so you can start working on the Scene2
return true
can do this.

if Setup1s(340,args1,kargs1):
	return Setup2s(20,args2,kargs2)

hope this adds to what you can do. bit of a disclaimer I just made the code shortly after you posted and didn’t really run it on anything so their might be a dumb mistake or gotcha that I did not catch, same with the explanation more of to teach the concepts. so not really copy paste able is what I am saying.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.