Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use C#/.NET in Godot 4.x: partial classes extending nodes, the PascalCase lifecycle (_Ready/_Process/_PhysicsProcess), [Export] fields, [Signal] delegates as C# events, GetNode<T>, and calling between C# and GDScript. Use when writing Godot game code in C# (.cs files, .csproj), needing the Godot .NET build, converting GDScript patterns to C#, or wiring Godot signals as C# events.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-14 | ✗→✓ | ▲ Improved | 102% | 0% |
| case-20 | ✓→✗ | ▼ Worse | 385% | 0% |
| case-22 | ✓→✗ | ▼ Worse | 96% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 236% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 55% | 0% |
Write Godot game code in C#: node subclasses, the engine lifecycle, exports, signals as events, and GDScript interop. Targets Godot 4.3+ (.NET / C#); install the .NET SDK that matches your Godot version — .NET 6.0 for 4.3/4.4, .NET 8 for 4.5+.
.cs + .csproj), translating GDScript idiomsto C#, exposing [Export] fields, or wiring [Signal] delegates and GetNode<T>.
When not to use: GDScript-specific syntax → godot-gdscript; engine concepts that are language-neutral (scenes, physics, animation) → the relevant godot-* skill. You need the Godot .NET build + the .NET SDK installed; the standard build can't run C#.
Godot 4.3/4.4, .NET 8 for 4.5+). Creating the first C# script generates a .csproj/.sln. Build with the editor or dotnet build.
partial class extending a Godot type (the source generatorrelies on partial). The file/class name should match the node script.
double delta: _Ready(),_Process(double delta), _PhysicsProcess(double delta).
[Export]; they show in the Inspector like GDScript @export.[Signal] delegates named XxxEventHandler; emit withEmitSignal(SignalName.Xxx, ...) and subscribe with the generated C# event.
GetNode<T>("Path") (or %Unique), and call into GDScript withCall/Get/Set when needed.
csharpusing Godot; public partial class Player : CharacterBody2D { [Export] public float Speed = 200.0f; // editable in the Inspector [Export] public float JumpVelocity = -400.0f; private const float Gravity = 1200.0f; private AnimatedSprite2D _sprite; public override void _Ready() { _sprite = GetNode<AnimatedSprite2D>("AnimatedSprite2D"); } public override void _PhysicsProcess(double delta) { Vector2 v = Velocity; // Velocity is a property here if (!IsOnFloor()) v.Y += Gravity * (float)delta; // delta is double; cast for float math if (Input.IsActionJustPressed("jump") && IsOnFloor()) v.Y = JumpVelocity; float dir = Input.GetAxis("move_left", "move_right"); v.X = dir != 0 ? dir * Speed : Mathf.MoveToward(v.X, 0, Speed); Velocity = v; MoveAndSlide(); // no args, like GDScript 4.x } }
csharpusing Godot; public partial class Health : Node { // Delegate name MUST end with "EventHandler"; generator creates the event + SignalName. [Signal] public delegate void HealthChangedEventHandler(int current, int max); private int _hp = 100; public void TakeDamage(int amount) { _hp = Mathf.Max(_hp - amount, 0); EmitSignal(SignalName.HealthChanged, _hp, 100); // type-safe signal name } public override void _Ready() { HealthChanged += OnHealthChanged; // subscribe like a normal C# event } private void OnHealthChanged(int current, int max) => GD.Print($"HP {current}/{max}"); }
csharppublic partial class Spawner : Node2D { // Load once; PackedScene is the C# equivalent of preload's result. private readonly PackedScene _bullet = GD.Load<PackedScene>("res://bullet.tscn"); public void Shoot(Vector2 at) { var b = _bullet.Instantiate<Node2D>(); // typed instantiate b.GlobalPosition = at; AddChild(b); } }
csharppublic override void _Ready() { Node gd = GetNode("GDScriptNode"); // Call a GDScript method and read/write its properties dynamically. gd.Call("take_damage", 10); int score = (int)gd.Get("score"); gd.Set("score", score + 5); // Connect to a GDScript signal by name: gd.Connect("died", Callable.From(OnDied)); } private void OnDied() => GD.Print("entity died");
partial. Without partial, the Godot source generator can't extend theclass and [Export]/[Signal] break with confusing build errors.
_Ready, _Process(double),_PhysicsProcess(double) — PascalCase and double delta (GDScript uses snake_case and float). A mismatched name just won't be called.
[Signal] delegate naming. It must end with EventHandler; the engine exposes thesignal as the name without that suffix and generates SignalName.X and a C# event.
GD.Print vs Console.WriteLine. Use GD.Print/GD.PrintErr to reach the Godotoutput panel; Console output may not appear.
Vector2, Color, Transform2D are structs — mutate a localcopy (var v = Velocity; v.X = ...; Velocity = v;); editing Velocity.X directly won't compile/persist.
.NET SDK causes build failures. Match the SDK to the Godot version (4.3/4.4 → .NET 6.0, 4.5+ → .NET 8; Android export on 4.5 needs .NET 9).
QueueFree() vs Free() — same rules as GDScript; prefer QueueFree(). Disposedobjects throw ObjectDisposedException if used after freeing.
the .NET export notes for your target.
[ExportGroup], ranges, typed arrays), async withawait ToSignal(...), Godot.Collections vs System collections, custom Resources in C#, and project/build setup, read references/csharp-setup-and-interop.md.
godot-gdscript — the GDScript equivalents of these patterns.godot-signals-groups — signal/event architecture (language-neutral).godot-resources — data resources; the C# [Export] + Resource pattern.unity-csharp-scripting — C# in Unity, for developers coming from there.Other measured skills in the registry, with their headline benchmark lift.