I had previously said I was going to code Fracterebus in Godot using GDScript for the flexibility of export targets it offers, but then I noticed three things.

The first one wasn’t really a surprise for me. I just really don’t like GDScript. It’s very Python-like and I have never liked that particular style of code, so by extension I found I was able to code in GDScript, but really didn’t care for it. I felt it was hard to find things in the code, tricky to keep things organized in a way that was compatible with how I like to do things, and thus slowed down my coding.

The second thing is that it’s missing some basics that I expected to be there, and ended up having to code myself. The particular offender that pushed me over the edge was having to code a heap data structure because it didn’t have one built in. Why code things that should simply exist already? Godot offers a C# version of the engine and I already know and like C#, so the switch makes sense for me.

The third thing I noticed while I was working on my port of TinyMT (Tiny Mersenne Twister) pseudo random number generator (PRNG). GDScript was weirdly slow. I’m has some advantages like excellent integration with the Godot engine itself, but as a fully interpreted language (at least for now), speed is not really one of the advantages. Before you get upset about this, I will clarify that most things you do in your game probably don’t need more performance than GDScript provides, so it might work perfectly for you.

Before making a final decision, since I’d already started things in GDScript, I wanted some metrics. Obviously there isn’t an easy way to get metrics on how much I dislike Python-like languages or how much time I would save not having to recreate basic data structures, so it really came down to performance. Having already ported TinyMT32 from the original C code to GDScript, I just needed to make a little test framework that I could use to run it a bunch of times as fast as possible and keep track of how long it takes. The heaviest random number use in Fracterebus is likely to be during world creation, and I guessed that process should fit into 100 million random numbers. I honestly have no idea, but that seemed like a big enough number to get a lot of work done, so I ran with it. Note that C# appears to have access to a higher resolution timer than GDScript does. That means there are way more decimal places in the number of milliseconds for C#, but that’s not something that meaningfully affects the outcomes.

GDScript Result

TinyMT (GDScript) - Seed: 0 (picking 100,000,000 random numbers)
Picked 100,000,000 random numbers in 125,077.0 ms (picked 799 numbers per ms)

In English, this means that GDScript picked 100M random numbers in just over 2 minutes and 5 seconds. At this point, I wasn’t sure if that was good or not, but the gauntlet had been thrown down.

The next step was to port TinyMT to C#. I decided to start with the original C code again for this process instead of using the GDScript version as a basis. Once again, I made a little test framework that did the same things the GDScript version did and fired it up within Godot.

C# Result

TinyMT (C#) - Seed: 0 (picking 100,000,000 random numbers)
Picked 100,000,000 random numbers in 2,753.5136 ms (picked 36,317 numbers per ms)

This means that 100M random numbers were picked like last time, but this time it did it in only around 2.7 seconds. That’s not just a little bit faster, that’s an incredible 45.42x faster for what is essentially the exact same task.

This meant that I now had three confirmed reasons to switch from GDScript to C# for Fracterebus. I like the language better, it has things built in that I don’t want to have to code for myself, and it’s apparently a pretty seriously faster, at least for this one particular task that I know I’ll need a lot.

In dramatic conclusion, I’ve started Fracterebus coding over again in C#, but I’m convinced now that this was the right choice.