Any tricks for extending a gdscript between two different extended classes?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By avencherus
:warning: Old Version Published before Godot 3 was released.

I have a situation where I’d like to extend from a gdscript, but I would also like to keep the node’s script extending their built in type.

I would have a RigidBody2D and a StaticBody2D, and they would want to inherit a bunch of general properties and initialization logic from a gdscript. I don’t want to create two copies that extend each type, because it will become a problem have to maintain multiple versions of the same thing as time goes on.

I know there isn’t any multiple inheritance for extends, so I can’t extend both and use it as a properties mixin.

Are there any eloquent ways around this? My initial idea is to preload the script as something like a props, and then refer to things like props.height, etc.

Any one else have any interesting alternatives?

You could do a component approach and put all the generic stuff in a script on a child node.

rgrams | 2016-12-02 22:58

I did something like that by just extending CollisionObject and using the script on Area or a PhysicsBody.

For simple things work but may give problems later.

Your idea sounds the safest/cleaner option.

eons | 2016-12-02 23:53

Alright thanks, eon, I wanted make sure I wasn’t overlooking something.

avencherus | 2016-12-03 09:22

If I’m not wrong, all your scripts can extend Node (or maybe Object or none) and will work fine on any Node, but is a kind of dirty way to work in Godot…

Another way could be using a child Node that adds behavior if you want more visual things (like debug tools, modify vars via Inspector)

eons | 2016-12-03 14:14

Oh, and something more:

If you need to play between different PhysicsBody, you can use all RigidBody in different modes, I believe that the server treats them according the mode.

Like a StaticBody is the same as a RigidBody in static mode for the physics server.

eons | 2016-12-03 15:52

Quite right. I was playing with that and discovered that the nodes preserve their type regardless of what sub class their script extends.

If you care to write it up as an answer, I’ll gladly flag it. For now I’ll leave my own.

avencherus | 2016-12-04 12:21

NOTE - Only works in older versions of Godot.

One way to achieving this is by having a base class that extends a common class. The node type in the editor will apply it’s type regardless of what parent class it’s script will extend.

So something such as this…

base_class.gd

extends Spatial

func common_function():
	return "something"

RigidBody

extends "base_class.gd"

func _ready():
	print(common_function())

StaticBody

extends "base_class.gd"

func _ready():
	print(common_function())

avencherus | 2016-12-04 12:25

Is fine with your answer.

I’m not sure if that is a feature or a bug, as feature is an overkill, one can make generic scripts and use them everywhere with behavior filter by type, group or metadata.

But I’m not sure if I like it…

eons | 2016-12-04 13:39

I know this is an old post, but the question is still relevant.
Anyway, at least in version 3.1, to use the class properties of the extending class (eg. RigidBody or StaticBody above), the engine will throw a compile error (method or property doesn’t exist in the class). To overcome this, simply do:

var body = self
body.some_func_on_body()

takaturre | 2019-04-13 03:11

I tried your suggestion and it worked nicely, since this post is old I wanted to ask you if you found any problems with this approach/technique, so far looks safe, clean an elegant to my eyes, thanks!

TGMG | 2020-06-18 18:51

@TGMG : Not sure for whom the question was… But I’ve now been using this kind of “cross extending” for about a year or two, quite actively in some cases, and haven’t had any problems, where this has been applicable. There are still cases where I’ve had to double the code due to more complex inheritance. Anyway, some notes:

  1. If you want to create a new node with your class with a specific internal class, first create a node of the desired class (eg. var node= StaticBody.new()) and then attach the script by node.set_script(my_script). (Doing var node = my_script.new() will use whatever base class the first script extends.)

  2. If you want to enjoy the GDScript’s typed hints and such, you can also do the below:

    var body : KinematicBody
    func _init():
    var _self = self
    body = _self

takaturre | 2020-06-20 12:11