The approach you would want to use in C# is different since the syntax is different. You won’t be able to directly convert your GDScript code to C#.
I primarily use C# for my projects and have implemented methods similar to the one you’re seeking to convert (see end of post).
Here is how I would implement the functionality of has_component
in C#:
public bool HasComponent<T>(this Node n, bool recursive = false) where T : Node
{
for (int i = 0; i < n.GetChildCount(); i++)
{
if (n.GetChild(i) is T)
{
return true;
}
else
{
if (recursive)
{
if (n.GetChild(i).HasComponent(recursive))
{
return true;
}
}
}
}
return false;
}
The primary feature of the C# language being used here is a generic type parameter (see MSDN). Using this parameter, you can run the code within the function for a specified type which, for most cases, should be named T
.
The type-testing is done with the is
keyword and the aforementioned type parameter, T
. Recursion is used to allow the function to detect all descendants of a particular node. This is enabled through the recursive
parameter which, by default, is false
.
The first parameter that uses the this
keyword is a direct reference to the node on which this method is called. This makes invocation of the method identical to how you’re currently invoking has_component()
. For example: entity.HasComponent<MovementComponent>()
.
I hope that helps. Let me know if you have any questions.
TryGetNode()
/// <summary>
/// Attempt to find a node of type, T, in this node's children.
/// </summary>
/// <typeparam name="T">Node type.</typeparam>
/// <param name="node">The found node.</param>
/// <param name="recursive">If enabled, performs this operation recursively to perform a depth-first search.<br />NOTE: Should probably be breadth-first.</param>
/// <returns>Whether a node was found.</returns>
public static bool TryGetNode<T>(this Node n, out T node, bool recursive = false) where T : Node
{
for (int i = 0; i < n.GetChildCount(); i++)
{
// GD.Print($"Checking {n.GetChild(i).Name}...");
if (n.GetChild(i) is T)
{
// GD.Print($"Found the {typeof(T)} node!");
node = (T)n.GetChild(i);
return true;
}
else
{
if (recursive)
{
if (n.GetChild(i).TryGetNode(out T recurseResult, recursive))
{
node = recurseResult;
return true;
}
}
}
}
node = null;
return false;
}
GetAllNodes()
/// <summary>
/// Finds all nodes of type T amongst this node's children.
/// </summary>
/// <typeparam name="T">The target node type.</typeparam>
/// <param name="recursive">If enabled, performs this operation recursively to perform a depth-first search.<br />NOTE: Should probably be breadth-first.</param>
/// <returns>All children of type T.</returns>
public static T[] GetAllNodes<T>(this Node n, bool recursive = false) where T : Node
{
List<T> nodes = new();
for (int i = 0; i < n.GetChildCount(); i++)
{
if (n.GetChild(i) is T nt)
{
nodes.Add(nt);
}
if (recursive)
{
T[] childResult = n.GetChild(i).GetAllNodes<T>(recursive);
nodes.AddRange(childResult);
}
}
return nodes.ToArray();
}