+30 votes

I have a simple scene that contains a Sprite node as its root. The sprite node has a SamplePlayer2D as a child.

I am a bit confused about how to pass 'constructor' parameters to this Sprite node when instantiating it from inside another scene. If I use ...

var mySprite = preload("res://mySprite.scn").instance() get_parent().add_child(mySprite)

... I seem to have no way to pass any parameters to the sprite's _init() function. if however I use...
var mySprite = preload("res://scripts/mySprite.gd")
mySprite.new(param_a, param_b)
get_parent().add_child(mySprite)

... then the sprite's child sample player is not created with it, as the whole packed scene has not been instantiated. I have a feeling I'm approaching the whole task the wrong way.

in Engine by (103 points)
edited by

As far as I know passing arguments for the constructor of scripts that are deriving from the Node class is prohibited simply because editor needs to know how to construct given node. Do what @atze suggested, or use exported variables and init object in ready.

2 Answers

+36 votes
Best answer

There probably are better ways to do this but here is what I did:

Create your own init() function in mySprite.gd and call it after instancing the scene.

var mySprite = preload("res://mySprite.scn").instance()
mySprite.init(a, b)
getparent().add_child(mySprite)
by (492 points)
selected by

Yes that's the good solution, as kubecz3k mentioned passing arguments to an instanced node constructor is not supported, because it would make it impossible to instance via the editor (which won't ask you to give the required arguments values).

So using a custom init() or setup() function is the simplest solution to achieve this behaviour.

Thanks all !

If this has answered your question, please select it as such

I like to make init(...) return self, so I can do:
var mySprite = preload("res://mySprite.scn").instance().init(...)
I also like to preload the script into a constant, just in case I need to use it more:
const MySprite := preload("res://mySprite.scn")
var mySprite = MySprite.instance().init(...)

@MonsterVial Glad I read this

–2 votes

In Godot 3.0 you would do this as follows:

In MySprite.gd:

func _init(param_a, param_b):
    #do your init

In another scene:

MySprite = preload("res://scripts/MySprite.gd")

var mySprite = MySprite.new(param_a, param_b)
by (101 points)
edited by

You might have misread or have not read all of the question. It's about initializing a Node not a Script.
You've written something similar to the lower part of the question, which explains why it doesn't work.

I know this wasn't supposed to be the answer for the question, but it helped me thanks!

God bless guys.

In 3.4 this causes an error. "Invalid call. Nonexistent function 'new' in base 'PackedScene'."

That's because you are instantiating a scene. This example is for instantiating scripts.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.