DEV Community

Serkan
Serkan

Posted on

Myth Busting C# in the Godot Game Engine

The purpose of this article is to do a bit of myth busting when it comes to C# in the Godot engine. Often it is thought that C#, as a strongly typed language, has very complex syntax and requires a lot of work to code even the simplest of things. The Godot documentation itself uses those reasons and examples to convince readers to use GDScript over C#. So this article will describe several GDScript features that often are thought to be impossible or “ugly” in C#.

1. Arrays

In GDScript arrays are dynamically typed and allow you to add different types of objects to a single array.

var arr = [1, 2, "hello", "world"]
Enter fullscreen mode Exit fullscreen mode

Whilst this could be done in c# too, it is not really recommended because it would be more advantages to use strongly typed array item types.

var arr = new object[2]{
    1, "hello"
};
Enter fullscreen mode Exit fullscreen mode

In C# this is an array of objects, which are an integer (int) and a string. The type of the items in the array are of “object” which is the lowest possible common denominator between these primitives that are an integer and a string.

Note:
In game development everything is related to some sort of logic of your game, which could be player controls, NPC logic or game states. So the given example of mixing unrelated types of objects might not always make sense and could make your code less readable. Taking an approach of always considering the logic and then creating arrays of items that logically belong together will make more sense. For example you could have an array of NPCs that are roaming the level so in your code your code you would reference them like this:

var npcA = new Npc();
var npcB = new Npc();
var arr = new Npc[2]{
    npcA, npcB
};
Enter fullscreen mode Exit fullscreen mode

Now, your array contains items of the same type and will allow you to handle your game logic better by using methods of the NPC class.

2. Duck typing

https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_advanced.html#duck-typing

Since C# is not a dynamic language, it doesn’t let you call methods (ignoring reflection) without ensuring at compile time that the given method exists. If you tried, it would result in a compile error.
Now, the Godot engines C# binding lets you also use the “has_method” and “call” methods on Nodes to handle this dynamically but for the sake of the article and strong typing, I will be demonstrating an alternative.
C# lets you do very simple pattern matching to figure out if the given object is of a type and then return the object as that type.

public void PlayerEntered(Node2D node)
{
    if (node is Player player)
    {
        GD.Print($"player has {player.Health} remaining");
    }
}
Enter fullscreen mode Exit fullscreen mode

In this code you can see that the argument is of type Node2D or Node which all items in a scene are. Then I can use the “is” syntax to identify if the types match and use additional syntactic sugar to declare a new variable “player” which is the node object as a player. Now I can freely use any public properties/methods on the Player class. It might not be duck typing, but its the next best thing that you can do with little code and it works perfectly.

3. For Loops

https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_advanced.html#for-while

In the Godot documentation for "for loops", strongly typed languages are depicted as features that have complex syntax that doesn’t make it readable and could easily allow errors.
However this is not true in C#. Whilst it is still possible to do for loops using the old traditional syntax:

for (int i = 0; i < 50; i++) {}
Enter fullscreen mode Exit fullscreen mode

it is easier to use the newer “foreach” syntax:

var strings = new string[2]{ "hello", "world" };
foreach (var s in strings)
{
    GD.Print(s);
}
Enter fullscreen mode Exit fullscreen mode

4. Looping through dictionaries

In C# it is also possible to loop through dictionaries the same way it is possible to loop through arrays and lists. Each item in a dictionary is of type KeyValPair where T is the type of the Key and TE the type of the Value.

var strings = new Dictionary<string, int>(){
    { "key1", 1 }, 
    {"key2", 2}
};
foreach (var s in strings)
{
    GD.Print(s.Key);
    GD.Print(s.Value);
}
Enter fullscreen mode Exit fullscreen mode

In this given example we have a dictionary of strings that hold a value of an integer. C# lets us access these values using the “Key” and “Value” properties and is capable of knowing its type at compile time.

As you can see C# is not all that scary and has many benefits when developing software, especially games.

Thanks for reading, and please let me know of any feedback you have.

Discussion (0)