**NOTE**: This proposal aims to be a public technical discussion regarding the f…uture of C# in Godot. The idea is to get help from the community to reach implementation direction consensus.
### Describe the project you are working on
Godot C# Bindings
### Describe the problem or limitation you are having in your project
The current implementatio of C# in Godot is done on top of the script layer directly and in C++ using the .NET hosting API.
This is due to how Godot worked in version 3. It currently has the following problems:
* Large amounts of C++ are required to glue Godot to the C# runtime, this makes it **difficult to maintain** and redundant with the new extension system in Godot 4. It is a lot of C++ code that supplies the same function as GDExtension.
* Many of the APIs exposed to C# currently are lagging behind what GDExtension provides, preventing many optimizations.
* It makes it harder to have a single version of Godot, because the large amount of glue code encourages users to switch it off when not needed to save space.
### Describe the feature / enhancement and how it helps to overcome the problem or limitation
The proposed solution is to move C# support to the new extension system in Godot 4.0.
This will give C# in Godot effective first class support at the same level C++ has, bringing the following features:
* The entirety of the C# glue layer (currently done via C++ .net hosting API) **will be majorly replaced by GDExtension**, using the extension interface common to all binding languages (GodotCPP, Rust, etc). The **modules/mono** folder will be removed from the codebase and likely replaced by only by a tiny boostrapper to load the .net runtime on demand if installed in the project.
* Because the entirety of the C# support will use the shared extension system (GDExtension), a single, **unified version of Godot and the export templates** will be possible.
* Some of the C# API, including the native Godot collections, will be changed for more efficiency (Example #[7842](https://github.com/godotengine/godot-proposals/issues/7842)).
### Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
**NOTE** This is a medium term goal for C#. Currently, our **immediate priorities** are **fixing C# support on mobile
and web**. What is described in this proposal is work that would happen in parallel.
Ideally, we want to **move Godot to use the GDExtension API** instead of the
current custom glue glue. Unlike GDExtension, though, we don't want to
depend on a glue API, it should be possible to open the .NET DLL
containing the Godot C# library and have it register itself via the
GDExtension API through a tiny boostrapper that detects if a .net runtime is installed.
This would **make the entire C++ side far simpler**, easier to maintain,
and easier to implement new features (such as many additions on the
GDExtension side currently are not supported in in the current module, such as GDVIRTUAL,
struct pointers, Godot collections, enhanced performance due to less glue, etc).
Additionally, it would make it easy to have **a single Godot executable**
and export templates, where C# can be plugged at run-time easily.
Here are the steps to evaluate that would be required to do this:
### Creation of a Godot Library in C#
The main idea is that **C# should act as if it was a C++ extension**. A library
(in the shape of a .net DLL), probably GodotLibrary.dll, can be added to
a project and this automatically is recognized and opened by Godot as if
it was a native shared object, but done actually via the .NET runtime.
In other words, if the C# runtime is installed in the Godot project (or
supplied by the platform to Godot), it is used to open GodotLibrary.dll
and call an entry point that should be the same as a regular GDExtension,
### Rewrite the extension interface in C#
Godot has a C [extension
interface](https://github.com/godotengine/godot/blob/master/core/extension/gdextension_interface.h)
defined in C. This extension interface should be available as part of
the GodotLibrary.dll C# source code. Probably something like
ExtensionInterface.cs.
This means making all the structs and C funtions available in unsafe
mode as their C# counterparts.
### Binder generation
Once we have the extension interface defined in C#, we can start working
on the binder generator. Before going into this, I think it's **important
to reach consensus** on whether we want to generate the bindings as scripts or
extension.
#### Bindings as extension or script?
Godot has two possible workflows today and both are supported in GDExtension: Script Workflow and Class Extension Wokflow.
Normally, script workflow is very quick and intuitive for GDScripts, as the steps to create a new script are:
* Select a node.
* New script wizard button.
* Automatically start editing it im the built-in editor.
* See changes and exported properties in editor automatically.
Blazingly fast. In contrast, for C# the script workflow is more cumbersome:
* Creating a script and placing it as a node in the scene tree:
- Switch to the C# IDE
- Create a new file in C#, tag it as script, compile.
- Switch back to the editor, reload happens.
- Create a new base node of the right type.
- Look for the script file, assign it to the node.
* Or alternatively:
- Create a new base node of the right type.
- Use the new script wizard to create a template .cs script
- Switch to the C# IDE
- Edit the script
- Compile
- Return to the editor.
The alternative is to implement C# using the Class Extension workflow. This workflow is the one compiled languages like GodotCPP, Rust, Swift, etc. uses.
In C#, it would work like this:
* Creating an extension class:
- Switch to the C# IDE
- Create a new class (no need to be new file) inheriting a node type, tag it as extension class.
- Edit it.
- Switch back to the editor
- Create the node directly as this class.
As you can see, when using compiled languages, there are not significant differences.
The question is, should C# using script or extension class bindings?
Here are the pros and const:
#### Script
Pros:
* Easy to switch one script by another during run-time.
* Soft reloading is a bit safer.
* Can edit C# scripts in the engine itself (though nobody really uses this, everyone uses external editor).
* Can theoretically debug C# in the editor (theoretically, but not currently supported and most users seem fine with the C# debugger of their IDE).
Cons:
* Less efficient for performance (more indirections). Many of codepaths goes via Variant conversion, which less efficient.
* Not great for add-ons. If you create a Terrain add-on, it will appear as a Godot node with a C# script rather than a native C# class.
* Not possible to replace parts of the engine (no custom audio formats, custom renderer, custom multiplayer driver, custom physics engine, etc.).
* Bindings code a bit more difficult to maintain.
#### Extension class
Pros:
* Very performant, integrates very well as if it was a native engine class.
* GDVIRTUAL (which is used for engine callbacks such as _Process, _Ready, etc.) a lot more optimal than in scripts.
* Struct pointers can be used in high performance APIs.
* Ability to replace internals of the engine.
* Simpler binding code.
Cons:
* Can't easily replace in run-time, must delete a node and replace by a new one.
* Soft reloading will work, but may be troublesome in some unexpected corner cases due to this process being a bit more complex (need to add and remove from ClassDB).
Should we use Script or Class extension workflow? That is up to you community.
My personal recommendation would be to go with Class Extension workflow primarily due to performance reasons. With this workflow you will be able to always have optimal performance in all situations and the alternations to ease of use are very minimal.
**EDIT**: I added a small poll a few coments below.
I put together a quick FAQ:
```
**Q**: Will I be able to reload extensions like scripts?
**A**: Yes
**Q**: If when loading a project, some extension class is missing, is this
lost upon scene load?
**A**: No, extensions create placeholders so you can re-save your scene and open
it again when the class exists.
**Q**: Can both workflows be provided?
**A**: There is some discussion on the GodotCPP side with this same question.
Its hard the same class is provided as both script an extension, so one
possibility is to have something like `CSharpScript<BaseClass>` you inherit,
then you access the actual engine class via a "base" property, example you
change position by doing `base.position = Vector2(20,30)`. This would allow both workflows.
**Q**: Will I have to redo my C# project if we go with Extension Class workflow?
**A**: Minimal changes will be needed and a converter for scenes can be provided
so the work you need to do is minimal.
```
#### New Bindings Generator
The new bindings generator would comprise of the following parts:
##### ExtensionInterface
As mentioned before, the
[extension_interace](https://github.com/godotengine/godot/blob/master/core/extension/gdextension_interface.h)
file from Godot rewritten in C# as ExtensionInterface.cs.
Everything else will use this and it replaces the **glue/** code in the
existing modules/mono codebase.
##### Glue
The C# side of the glue that previously existed in mono/glue, which will
need to be used by both Godot Types and the bindings generator. This
talks to **ExtensionInterface.cs** to ensure that types such as
Callable, Signal and a few low level behaviors in the class bindings can
be implemented properly.
##### Godot Types
These are the basic Godot types (Vector3, Vector4, Transform2D, etc)
exposed to C#. They are currently located in [this
directory](https://github.com/godotengine/godot/tree/master/modules/mono/glue/GodotSharp).
As mentioned before, not all need to be written natively, some now can
be done 100% by using the binding generator.
The Godot collections (the way C# calls Godot PackedArrays, Array,
Dictionary) currently are not properly implemented in C#, C# always does
conversion from native C# types to Godot types on every call. Ideally
this should be kept because it makes the API easier to use, but all the
Godot array types and dictionary should be properly supported as
Godot.Collections. This will allow properly implementing proposal
#[7842](https://github.com/godotengine/godot-proposals/issues/7842).
Additionally, as mentioned, some may need minor changes, such as
Callable or Signal, which now need to use **ExtensionInterface.cs**.
##### Bindings Generator
This is **the largest part of the work**. The new bindings generator can
be written in Python, C# or whathever decided best. It takes an
**extension_api.json** file and dumps the whole Godot API as C#.
All the classes, utility functions (currently hardcoded), and several
other binding information is used to **create the Godot API in C# entirely**
in procedural form. Again, no C++ glue code should be needed anymore. Everything accessed via **ExtensionInterface.cs**.
Additionally, this should use the compatibility hashes system in
GDExtension, so we can ensure that backward compatibility is also kept
in C# when Godot releases new versions.
Currently, Godot C# uses API hashes, again those need to be dropped entirely and **API hash support removed from Godot**.
##### Editor Tools
Finally, porting the existing editor tooling to the new system. Most
code probably will remain unmodified.
##### Boostrapper
A small piece of code to load the .net runtime (if installed by the user), that calls the C# entry point.
### Assembling the GodotLibrary.dll
The GodotLibrary.dll will be **built from the existing and generated C# files** created by the bindings generator script.
On PC platforms, It will be shipped in Godot together with:
- C# runtime (where applies)
- Respective additions to export templates to enable deploying using C#
- Respective tools to help users build C# in their project using the
GodotLibrary (in editor build).
### Compiling the game
C# games in Godot would simply be a library compiled against
GodotLibrary.dll and other .net dependencies. This step is the same as now.
### Deploying to platforms
An important question here is how will this be ported to different
platforms (iOS, C#, etc).
Essentially, **nothing should really change**. Platforms that run JIT will
ship with the runtime.
Platforms that use NativeAOT will need to just change how the entry
point is accessed, but all the work is now done inside C#, so all Godot
cares is reaching that entry point and that's it.
### Closing words
Thanks for reading the C# roadmap so far. Feel free to discuss what you think in this proposal!
### If this enhancement will not be used often, can it be worked around with a few lines of script?
N/A
### Is there a reason why this should be core and not an add-on in the asset library?
The tiny boostrapper will be core, the rest obtainable separately.