Godot Version
4.5.1
Question
Is it safe to overwrite the “new()” function when creating a custom class?
I assume so, since the editor has not complained, but I felt like it was better to make sure
Realized it’s better in the long term to have a certain class instantiate itself, including because this way if you reorganize the files you only need to update the path in one place. Also if the setup changes, the editor will automatically warn of any “new()” that is now missing info, rather than me having to remember everywhere that uses that class and changing the initiation there
But making up arbitrary names for each of them (“create_[class name]”) feels like it would easly turn into a memory problem for the humans involved. So, this feels like the perfect use for the new() function
You shouldn’t do this but instead use _init for this
Thank you. In the short time since writing this post I realised my mistake since Godot warned me new takes no arguments, despite my attempt to rewrite it.
If I understand correctly, you are supposed to explicitely call _init after new, such as:
var c = MyClass.new()
c._init(atr1, atr2)
Only problem with this is that it doesn’t instantiate a custom .tscn like I wanted to. I was making a function a la:
static func create() -> MyClass:
var mc = load([path]).instantiate()
[does instantiation]
return mc
No. _init() is a constructor. It’s automatically called by the built-in new(). You can even supply arguments to new() that will be forwarded to _init(). You typically never call _init() directly.
Scene instantiation will create nodes in the scene, internally calling new() for each of them.
There is a caveat here though. When new() is called by the engine, and you’ve defined the constructor, make sure to have default values assigned to every argument so that engine can call it without passing any arguments. Otherwise you’ll get an error and the constructor won’t be called.
So if one was o create a node with children using new, they would have to be created and added as children during _init?
Seems that creating a custom function might be the easiest alternative after all
new() has nothing to do with children. It just allocates an object of the class.
instantiate() is a different beast altogether. It’s a method that can only be called on PackedScene object. It will in turn create all node objects that are packed in the scene, one by one, calling new() for each, then link them into a tree hierarchy and return the top node in that hierarchy.
I understand how instantiate works, thank you
I have created certain scenes meant for flexibile use, and I assigned the root node of those scenes code wich gives them a unique, new class (class_name)
I was thinking of a way to create scenes from that class, including the children nodes, that is done inside the code of the class, recieving info when created
My previous solution was simply to create a static func on the class that returns an instance of the scene, such as:
static func create(arg1, arg2) -> MyClass:
var mc :MyClass = instantiate([path]).instantiate()
[uses the arguments]
return mc
Since this way a single place in the code has to worry about weather the path changes, if the setup process changes, the editor automatically picks up weather one or more of the necessary arguments change, etc.
I though maybe the new function could be used for this, seen as plenty of nodes have built-in children (Windows come with buttons, tabContainer with a tabbar, wich in turn has tab children). It seems I was mistaken, and doing so is either impossible or impractcal
What exactly are you trying to make. What’s the concrete use case?
The example that got me here would be the RecordLabel. Besides showing the record it also shows art indicating the place of the record (first place, second place, etc.). It also warns the TTS what to say once it recieves focus and on the appropriate key presses, as well as keep the children centralized as it, a container, changes size
You can implement an initializer function in the top node script that configures the whole scene. Then call that immediately upon instantiation, exactly like you above wanted to do with new()
Would you have an example of what you mean please? How would it be superior to the example “create” function please?
It’s basically the same thing. Having an explicit initializer function would be useful in any case as you can call it again later if you need to re-initialize.
Alright, got it, thank you. Guess I’ll just try to use the same name for the functions so it’s easier to remember
Something like this:
class_name MyClass extends Node
func _setup(params):
# stuff
static func create(params) -> MyClass:
var top_node: MyClass = packed_scene.instantiate()
top_node._setup(params)
return top_node
1 Like