What does it really mean when a script is attached to some node? Documentation seems to act like the script is effectively extending the node type via some kind of inheritance. However, if it was truly inheritance then Godot should restrict scripts to only be attachable to a node of type A if that script extends type A. But it doesn’t. For instance, Godot allows me to attach a script to a MeshInstance3D despite the fact that the script only extends Node. So if I do something like this what is really going on? It seems to act more like composition.
My follow up question to all of this is would there ever be a benefit in directly attaching a script that extends A to a node of type B (where A and B are different)?
As far as i understand, and i could be wrong, by not giving it any other inheritance other than “node” then those are the only functions you can run. There’s probably niche use cases, like i might make an information reference class to store a lot of variables in one script full of libraries, and then various other scripts that extend from it to handle individual information exchange on the given node.
As for your follow up, this is how classes work. You can assign a script to be a class, then reference that class, and all the functions that class extends from other scripts that extend your class script. This can be used to add similar functionality across many instances. This is commonly how things like weapons, or bullet types, or even players and enemies.
Ya I understand the concept of inheritance. I am specifically asking about how the concept of class inheritance in a script relates to the “attachment” of that script to some node. Typical practice is that the script you attach extends the type of node you attach it to. That is how the editor sets up new scripts by default when you click the “attach a new script” button for some node in your scene. However, you are allowed to change the class that this script extends to be something else entirely and I’m just curious what that is supposed to mean in general.
Im not sure it means much of anything tbh, as i cant imagine the functions of say the 2DCamera would mean anything to the 3DPlayerController. Might spit out an error, might have unintended results? Try it for yourself?
Im not experienced enough to answer properly it seems, sorry.
I understand where you’re coming from, but this is not what happens. Godot does not support multiple-inheritance. It also only supports composition through nodes.
If you attach a script to a node, you are changing its type either to the class_name declared in the script, or as an unnamed class that inherits from either the named class (such as extends Node) or from RefCounted if no extends clause exists.
Since RefCounted inherits from Object and you must extend an existing class (Object being the lowest level possible in Godot) any script attached to a node makes it an Object. If you do not attach a script, you are using the default script which was used to create the Node to begin with.
So, lets say you create a Node2D and then attach a script that extends CharacterBody3D. What you are doing is confusing yourself and anyone else because the node appearance in the editor is that of a Node2D, but it is in fact a CharacterBody3D and will act that way. This is user error, but Godot lets you do it. In this case you are overwriting the existing class and making it a completely new class.
So I ran a couple more tests and it seems Godot throws a runtime error if the script extends a type unrelated to the node its attached to or if it extends a (strict) subtype of the node. I had thought I tried this and didn’t get an error before but I must have been mistaken.
What Godot does allow without run time errors is attaching a script of type A to a node of type B if A is an ancestor of B (e.g. attaching a script which extends Node3D to a MeshInstance3D). In that case the script just has limited access to the full capabilities of that Node similar to what @Tedward suggested in their initial reply. I assume the use case in there is if you have a situation in which you dynamically attach scripts at runtime and you want to be given the flexibility to attach the script to Nodes that extend whatever the type of that script is for polymorphism.
edit: thanks for indulging in my strange question y’all.
I was wrong in my previous post. But it’s been a while and I’ve learned some things. You’re right, you cannot assign a Node3D script to a Node2D script and just change all its properties. But you also should not be doing this.
As I stated before, the script determines what the object is, just like any other language that supports classes.
That is an erroneous assumption. You cannot attach new scripts to nodes at runtime. Whatever script is attached in the editor gets instantiated at runtime.
But like I said before, just because you can do stuff like this doesn’t mean you should.
In fact since 4.5.1, any GDScript you give a class_name to can be created in the Add Node dialog. You should always just use the node intended, and if you want to swap nodes out, swap nodes out. Don’t try to swap scripts out on some base node to create a weird pseudo-polymorphism.