Essay - Published: 2022.11.09 | csharp | fsharp | godot |
DISCLOSURE: If you buy through affiliate links, I may earn a small commission. (disclosures)
If you are running Godot 4, refer to the Godot 4 guide instead.
F# has quickly become my favorite programming language / ecosystem. Yet it is still behind in direct support in many domains - game / 3D development included - meaning a bit of tinkering is required to get up and running.
In this post, we'll walkthrough setting up a Godot project that can run scripts in both C# and F#.
dotnet command to create and modify .csproj and .fsproj files
Note: you can grab the full Godot and F# project source code on GitHub.
The first thing we'll do is create a new Godot project that is C# and F# compatible.
.csproj and will enable C# script support for our project
Scene Explorer and going through the options to create a new C# scriptOur project should now have C# support. We can check this by creating an empty node in the project and attaching a simple script that will print to console. When we run it, we should see the output in our console.
SimplePrintCs.cs
using Godot;
using System;
public class SimplePrintCs : Node
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
GD.Print("SimplePrintCs: C# Running...");
}
}
When we run our Godot project, we'd expect it to output:
SimplePrintCs: C# Running...
Note: you can grab the full Godot and F# project source code on GitHub.
Now that we have a .csproj in our Godot project, we can start to modify it to enable F#.
First we'll create an F# library project.
ScriptsFs)cd ScriptsFs)dotnet new classlib -lang "F#"This should output a minimal F# project with an .fsproj and an example .fs script.
Now that we have this minimal F# project, we need to modify its build dependencies in .fsproj to make it compatible with our Godot project and scripts.
Open the .fsproj and make changes to match the .csproj:
Sdk - At time of writing the current Godot LTS is Godot.NET.Sdk/3.3.0 but this may change and the important thing is that .csproj and .fsproj match. By referencing the Godot SDK directly, we give our F# code access to the Godot APIsPropertyGroup > TargetFramework - At time of writing, Godot is targeting net472, but again the important part is that your .csproj and .fsproj agree on targets.At this point we have a C# project and F# project that understand Godot, but they don't yet know about each other. We can change this by adding a project reference from our .csproj to our .fsproj - this will allow our C# code to call into our F# code.
Add a reference from C# to F#:
.csproj is)dotnet add ./CSPROJ_NAME.csproj reference ./ScriptsFs/ScriptsFs.fsproj
CSPROJ_NAME with the actual name of your .csproj)With any luck we should now be able to call our F# code from C#.
Godot knows about our C# project and our C# project knows about our F# project but currently Godot does not know about F# so it can't directly call it. There are some workarounds to this on the web but I find them to be a bit to clunky and manual so instead of enabling that, we'll just call all F# from a base C# file.
When you want to reference F# scripts in Godot, we'll do something like this:
So let's say we want a script that prints to console. We can write that in F# like this:
SimplePrintFs.fs
namespace ScriptsFs
open Godot
type SimplePrintFs() =
inherit Node()
override this._Ready() =
GD.Print("SimplePrintFs: F# Running...")
Note: Make sure you update your .fsproj so it knows to compile this new script!
Now we create a placeholder C# file which we'll attach to our Godot scene to faciliate the Godot -> F# connection. The placeholder C# file just inherits directly from our F# file allowing it to run directly.
SimplePrintFsHolder.cs
using ScriptsFs;
public class SimplePrintFsHolder : SimplePrintFs
{}
Now when we run this, we expect to get both the C# and F# prints!
SimplePrintCs: C# Running...
SimplePrintFs: F# Running...
Hopefully this gets you started on your Godot x F# journey!
The best way to support my work is to like / comment / share for the algorithm and subscribe for future updates.