Trouble with godot class/struct inheritance C#

Godot Version

4.7

Question

Hello everyone. So I came from other engines and so far I’m loving the engine.
However there is something that is frustrating and I can’t seem to understand or fix in Godot.

Example code just for visualising.

public partial class Base : Node2D
{
    [Export] public int SpawnChance = 100;
    [ExportGroup("Random X")]
    [Export] public int DifferentialX;
    [Export] public int StepX;

    [ExportGroup("Random Y")]
    [Export] public int DifferentialY;
    [Export] public int StepY;
}

public partial class Enemy : Base // This needs to be a CharacterBody2D
{
	[Export] public IntRange Speed = new IntRange();
	[Export] public double DecisionInterval = 1.0;
}

public partial class Sprite : Base // This needs to be a Sprite2D
{
	[Export] public Texture2D[] Images;
	[Export] public Sprite2D MySprite;
}

I want to have a Base class that is going to work as a Base object for everything. In this case it can be a Node2D.
Then I want to have a Tree for example that is Sprite2D and inherits from the Base.
Right here is the first problem. I can’t access directly the Sprite2D because Base is a Node2D. So I can change the Base to a Sprite2D (which later is not going to work) or I can attach the Base and the Tree script to 2 different nodes in the scene this way its going to work. However when I instantiate the Tree scene I don’t have access to the exported properties in the Base or Tree because it’s a child Node (yes I can’t activate to show the child, but I don’t want that it gets very confusing very fast).
And then I want to have an Enemy that also inherits from the Base and the Enemy is a CharacterBody2D.

So how can I inherit from the CharacterBody2D and the Base at the same time. In C# is not possible, I can use resources but they are instance shared and they make the code way messier. I can also you normal classes and instantiate them but then I need to export everything when I put it on a new “child” class which is more duplicated code.
I can also create an interface, however I duplicate the code again because when I add a property to the Base I need to add that to all the interfaces , so that’s not a solution.

I hope I could explain the problem. Can anyone explain me how to do this.
This is getting very frustrating since I’m making a procedural generated game this is essential.

Thank you

The easiest thing to do, would be to attach a child node to every node that needs the procedural generation info. The child node (called e.g. GenerationData) contains all details. It can then be easily accessed by the parent node through GetChild<GenerationData>("GenerationData").ExampleData.

Alternatively, almost all classes in the Godot namespace inherit from GodotObject. GodotObject has a function GodotObject.SetMeta(StringName name, Variant value), which allows you set some metadata. However, you would need to copy this data to every child node when it is added to the scene from its parent (on enter_tree, get parent node, copy all metadata from parent to child).

From there, you can create a helper class that interfaces with the metadata of a GodotObject and provides the functions you’re looking for. C#'s extension methods are pretty neat for this. Though, I recommend just attaching a node.

Consider reviewing some sections of Game Programming Patterns by Robert Nystorm, in particular the component chapter to help with the architecture of your game. The book is written using approachable language, and explains concepts rather well, while not taking itself too seriously.

Personally, I would consider divorcing the spawn distribution from the logic of the node.

To expand on my previous post, the reason I suggested to create a child node with the generation details, is that that’s how composition would work in Godot/C#. Godot makes heavy use of the composition pattern (which I linked to). I don’t think that its a good way to add the information you’re keeping in the base class, however.

Inheritance in Godot is generally used to augment behaviour of the base node. Your Base class does not add new behaviour, but adds data that could be treated as a component, arguably elsewhere.

My proposed generation component would be (presumably) providing information on how it the procedural generation system behaves. This sounds like a concern for the procedural generation system. In addition, I am not exactly sure how this would be useful in an instanced node, let alone 50 of them.

To me, this information would be a lot better as a Resource (a lot like a ScritpableObject in Unity). This resource would store e.g. the enemy you want to spawn, along with the other details in your Base class. The procedural generation system would have a collection/array of these resources, that tell it what to spawn and where. That way there is one place with the details, as presumably you wouldn’t want these details to be stored with every instance.


Your confusion with interfaces isn’t uncommon. An interface is more a way of interacting with a class by guaranteeing certain properties/methods will be there, than it is a way to add this information. Once you get a hang of interfaces in C#, it makes creating reusable, decoupled code very easy.

An interface is better for creating e.g. IDamageable, where how each class interacts with it would implement this very differently. For example, both a Car, Light, Player may be damageable, but all would handle it very differently.

On the other hand, abstract class is better for guaranteeing certain (but not all) implementation details, providing a loose common base, or consolidating interfaces. An example would be public partial abstract class Explodable: RigidBody3D, that would guarantee that a rigid body has a force applied, but not how it interacts with e.g. the points system, or how other visual effects are implemented. See footnote 1.

As much as these are technicalities of C#, in my experience it really helps to design better object oriented code than C++ does. Also prevents strange issues like accidentally inheriting the same class twice.

At risk of repeating myself, I really recommend reading Game Programming Pattern by Robert Nystorm to get an idea how architect game code. I posted the link in a previous reply.


[1] Using an abstract class is not be the best way to implement an explodable system. I’d rather make this a non-abstract class that would have a signal Exploded that’s connected to e.g. the particle system to play particles as needed. That way, there is less code overhead when creating e.g. a chest that explodes and dispenses special items. The dispensing logic would be yet another component that is triggered on a signal.


  1. 1 ↩︎

Thank you so much for your reply.

I ended up reading some of the things you sent and went for the child node approach. Where I attach the script to a child node on the scene that has the generation information and handles that.
And to fix the problem that the exported properties of the child nodes don’t show on the root.

I created a plugin for that: TiagoCamacho/ExposeMe

So, so far so good. Problem solved :smiley:

Thank you