Including Rust code in a Godot Game

(learn about this date format)

As I’ve written about previously, I want to create a game that uses the Ring Fit Adventure accessories, and I want to make it using Godot 4. The item currently on my to do list is Investigate options for including Rust code in Godot games.

The candidates

Godot provides many different options for integrating code into projects. If I tried hard enough, I could probably find a way to make all of them interface with Rust code. The question is: which one makes the most sense in this particular situation?

C#

Including C# code in Godot projects has some inherent disadvantages. For one thing, the standard version of Godot doesn’t support C#. Instead you have to download the Mono version to get C# support. That Mono version of the editor has an additional dependency: the .NET Core SDK. I don’t find those two requirements to be much of an obstacle personally, but I can see it being unappealing to developers who might otherwise use or contribute to my code. In that same vein, developers working with Godot probably know GDScript. There’s a much smaller chance that they know C#. Using C# would limit the potential number of users and contributors.

Similarly, Godot has two different types of export templates: standard ones and Mono / C# ones. Each of the C# templates is larger that its standard counterpart. For a single download, the difference probably isn’t noticeable, but for many downloads overtime, the bandwidth costs will add up (or not, I don’t really know that much about Web hosting).

Another thing that I dislike about C# is that it’s not platform neutral. When you write code in C, you end up with extension-less executable files and .so files on Linux and .EXE files and .DLL files on Windows. When you write code in Java, you end up with .JAR files and .class files on both Linux and Windows. When you write C# code, you end up with .EXE files and .DLL files on both Linux and Windows. I definitely don’t want to make people’s Linux installations more Windows-y.

Another problem is that C# support in Godot 4 isn’t very stable. According to the release notes for the latest snapshot of Godot 4, Mono builds are currently not available as our focus is on porting to .NET 6. You'll get a chance to test it with later alpha releases!

Additionally, while doing research for this post, I found the following quote:

.NET 20th anniversary

Tune in on February 14 to watch the broadcast, share your stories on Twitter using the hashtag #dotNETLovesMe, and have fun celebrating 20 years of innovation.

Join the celebration

.NET Downloads (Linux, macOS, and Windows) ()

If something is truly innovative, then its creators probably wouldn’t be saying that it’s innovative. More importantly, if you truly believe that .NET loves you, then you have mental problems. I don’t like the idea of using people’s mental problems for marketing purposes.

After all of that, is there any advantages to using C#? I can think of one: C# is more established than Godot. If I can’t find a good way to include Rust code in a Godot game directly, then I can certainly find a way to include Rust code in C#.

VisualScript

From what I can tell, any APIs available to GDScript are also available to VisualScript. An important difference between the two is that VisualScript’s target audience is people who don’t have much programming experience. I’m not one of those people, so I don’t think that it makes sense for me to use VisualScript.

GDScript

GDScript makes some sense seeing as it’s Godot’s main programming language. The problem is that GDScript doesn’t have much support for foreign code. GDScript can access functions exposed using any of the other candidates, but GDScript itself doesn’t really have a foreign function interface. The only way to get information from foreign code using purely GDScript would be to call something like OS.execute() and then monitor stdout.

GDExtension

At the moment, documentation for GDExtension is sparse. The main documentation that exists for it is this blog post. When I tried the test project that that post mentions, it built successfully but crashed Godot when I tried to open it. It also looks like that project won’t be updated. I read the rest of the blog post, but most of it went over my head. It looks like I don’t know enough about C++ and Godot’s internals to use GDExtension yet.

godot-rust

godot-rust is very close to being a good option. godot-rust would allow me to create a Godot “script” using Rust, and then attach that script to a Node. This is exactly what I’m looking for. The problem is: godot-rust depends on GDNative. GDNative is being replaced by GDExtension in Godot 4. godot-rust doesn’t support GDExtension yet because GDExtension isn’t stable enough.

Writing a custom module

From what I understand, custom modules are very similar to GDExtension extensions. The biggest difference is that custom modules require you to compile your own versions of Godot. I’m not sure what the advantage of creating a custom module would be, but I’m guessing that, compared to extensions, modules are able to do more (i.e., they have access to a larger API).

Unfortunately, I don’t know very much about C++, I don’t know enough about Rust, and I know nothing about interoperability between C++ and Rust, so this doesn’t seem like a good solution either.

Conclusion

Yet again, the best option is one that doesn’t exist yet. I’m stuck waiting for godot-rust to wait for Godot. In the meantime, here’s what I’ll do:

  1. Create a Rust program that prints the information that I need to stdout.
  2. Create a Godot asset that provides an API for receiving data from Joy-Cons and Ring-Cons. For the moment, this asset will be written in GDScript. It will run the aforementioned Rust program and parse its stdout.
  3. If godot-rust gains Godot 4 support, then transition the asset to use godot-rust.
  4. Eventually, if godot-rust never gains Godot 4 support, turn the asset into a GDExtension extension or a custom module.