Godot: [Solved]A way to instance node with parameter

Created on 5 May 2019  路  9Comments  路  Source: godotengine/godot

Is there a way to pass some parameter to a node when instancing it? I mean the same time, not define a custom init function and then call it later, that will cause some async problem. Or can a node can know who instance itself, so we can use get_parent() to get param. I think if there is a way like than, code will be more simple. Or just because that will cause some performance issue?

archived feature proposal core

Most helpful comment

This would useful in scene testing. Because we don't know if pseudo-constructor is already called or not.
Let me give an example. I have a init() function as an alternative to scene constructor with optional parameters. When instancing in another running scene(Main.tscn) I can call it with parameters. But, I have no way to call it when I run/play(F6) just the scene(Parts.tscn).

Let this be Main.tscn's main_game.gd:

export(int) var No_Of_Levels=0
var bd=load("res://Parts.tscn")

func _ready():
    var x=bd.instance()
    x.init(No_Of_Levels) #pseudo-constructor call
    add_child(x)

Let this be Parts.tscn's Parts.gd:

var curr_player
var part_id
var level

func _ready():
    #init() #This can't be un-commented because then init() would be called twice when instance in another scene
    pass

func init(lvl=0,p_id="0",startplayer="X"): #pseudo-constructor
    #some action like follows
    level=lvl
    part_id=p_id
    curr_player = startplayer
    reset_board()
    var a = connect('board_done', get_parent(), 'set_cell')
    if a==0:
        print("Level ", level, " Board ", board_id," is connected.")
    else:
        print("Level ", level, " Board ", board_id," failed to connect.")
    #some action like above

Having a instance with parameters would solve it because then I could just rename my init to _ready; And instance with bd.instance(1,1,"Y").

All 9 comments

If a packedScene's child node need get param who instance it, that will be a little problem, I should call every child in packed scene to change the var. The only way I think better is use the singleton to pass the param, but I think that's not naturally

But you can set any properties after instancing and _ready() is called after adding to scene. Not sure why would you need some instancing parameters. Like

var node = preload("res://somenode.tscn").instance()
node.some_variable = some_value
node.creator = self
add_child(node) #here the _ready() is called

There aren't any "async problems" with that.

There's absolutely no "async problems" in setting a node's variable just after it's instantiation.

Thank you guys, I see that a node wont instance child before adding to the tree

I think if godot give a virtual function order, then everyone know how does it work. Just like the"ready", "enter tree", "draw", "input", "unhandled input", sometimes I feel confuse to the order they run

I think if godot give a virtual function order, then everyone know how does it work.

Eh, is there any tutorial about that or any reference point in docs? If not, this could be changed to documentation issue.

This would useful in scene testing. Because we don't know if pseudo-constructor is already called or not.
Let me give an example. I have a init() function as an alternative to scene constructor with optional parameters. When instancing in another running scene(Main.tscn) I can call it with parameters. But, I have no way to call it when I run/play(F6) just the scene(Parts.tscn).

Let this be Main.tscn's main_game.gd:

export(int) var No_Of_Levels=0
var bd=load("res://Parts.tscn")

func _ready():
    var x=bd.instance()
    x.init(No_Of_Levels) #pseudo-constructor call
    add_child(x)

Let this be Parts.tscn's Parts.gd:

var curr_player
var part_id
var level

func _ready():
    #init() #This can't be un-commented because then init() would be called twice when instance in another scene
    pass

func init(lvl=0,p_id="0",startplayer="X"): #pseudo-constructor
    #some action like follows
    level=lvl
    part_id=p_id
    curr_player = startplayer
    reset_board()
    var a = connect('board_done', get_parent(), 'set_cell')
    if a==0:
        print("Level ", level, " Board ", board_id," is connected.")
    else:
        print("Level ", level, " Board ", board_id," failed to connect.")
    #some action like above

Having a instance with parameters would solve it because then I could just rename my init to _ready; And instance with bd.instance(1,1,"Y").

I can't agree more.
The _init() is called automatically when new a node.
And if call new with parameters, like Scene.new("a", "b"), the func _init(a, b) would be called as a constructor. That's good.
However, in most situations, PackedScene.instance() would be used to instance scene. then the only _init() without any parameters would be called. It's not possible to pass parameters to the scene.
If the instance can be declared as
Node instance( GenEditState edit_state=0, ... ) , the _init constructor would be really useful.

Also, this can be used for the change_scene as change_scene(String path, ...)

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!

Was this page helpful?
0 / 5 - 0 ratings