Godot 4
How do I properly instantiate a generic class?
Hi, I’m very new to Godot, but I’ve got a little bit of experience when it comes to programming otherwise and I’ve been trying to use C# to make use of Interfaces and Generics. I noticed however, that when I wanted to use a generic class as a node, that I can’t properly use GetNode<>()
with it. Here’s what I mean:
This is my generic class:
public partial class StateMachine<T> : Node where T : Node, IState<T>
where IState<T>
is an Interface for states used in the state machine. Here’s the code for completion:
public interface IState<T> where T : IState<T>
It will be used to create groups of states like this:
public abstract partial class PlayerState : Node, IState<PlayerState>
{
public Player Player { get; set; }
public VelocityComponent Velocity { get; set; }
This way I have functions defined which all states need and can add custom properties to every state of a specific state machine using abstract classes.
I hope I’ve painted the picture of what kind of architecture I’m trying to build. This all works fine, but now comes the part, which gives me some headaches:
When trying to use the expression
GetNode<StateMachine<PlayerState>>("StateMachine")
godot tells me during runtime: “ERROR: System.InvalidCastException: Unable to cast object of type ‘Godot.Node’ to type ‘StateMachine`1[PlayerState]’.”, which makes total sense, because the particular instance of StateMachine<T>
is not instantiated as a StateMachine<PlayerState>
.
Is there any way to change how the class is first instantiated?
My first workaround was replacing the node using ReplaceBy()
:
public static T ReplaceNodeByGeneric<T>(NodePath nodePath, Node currentNode) where T : Node, new()
{
var oldNode = currentNode.GetNode(nodePath);
oldNode.QueueFree();
var newNode = new T
{
Name = nodePath.GetName(nodePath.GetNameCount() - 1)
};
currentNode.GetNode(nodePath).ReplaceBy(newNode);
return newNode;
}
which is called in the parent node, but this seems very much not like a good idea for many reasons.
PS:
While writing this I realized that I can create an empty class which inherits from a specificly typed StateMachine
public partial class PlayerStateMachine : StateMachine<PlayerState>
{
}
and attach it to my StateMachine
node. However, this means I still can’t use exported variables, but I have a hunch that that’s impossible as long as StateMachine
is generic.
I’m still curios if there is another way to go about this or if even my entire approach is a bad idea. As I said, I’m pretty new to Godot and game engines/development in general, but I wanna have a solid architecture when it comes to stuff like state machines and dependency injection.
I appreciate any tips, ideas and resources! <3