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.
.claude/skills/gamedev-skills-godot-csharp/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 207% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 248% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 388% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 108% | 0% |
Write Godot game code in C#: node subclasses, the engine lifecycle, exports, signals as events, and GDScript interop. Targets Godot 4.7 (.NET / C#) and .NET 8.
.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#.
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. Godot 4.7 targets .NET 8; check current platform export notes because Android and other AOT targets can require newer SDK tooling.
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.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 3,784 | 2,389 | -37% | 1 | 1 | 0% | 627 | 2,180 | +248% | 0 | 0 | — |
case-02 | pass→pass | 2,841 | 2,302 | -19% | 1 | 1 | 0% | 439 | 2,143 | +388% | 0 | 0 | — |
case-03 | fail→pass | 4,925 | 4,960 | +1% | 1 | 1 | 0% | 869 | 2,668 | +207% | 0 | 0 | — |
case-04 | pass→pass | 7,934 | 7,148 | -10% | 1 | 1 | 0% | 1,500 | 3,122 | +108% | 0 | 0 | — |
case-05 | pass→pass | 10,418 | 6,293 | -40% | 1 | 1 | 0% | 2,123 | 2,887 | +36% | 0 | 0 | — |
case-06 | pass→pass | 5,656 | 4,877 | -14% | 1 | 1 | 0% | 1,051 | 2,722 | +159% | 0 | 0 | — |
case-07 | pass→pass | 5,742 | 3,849 | -33% | 1 | 1 | 0% | 1,046 | 2,473 | +136% | 0 | 0 | — |
case-08 | pass→pass | 5,640 | 4,168 | -26% | 1 | 1 | 0% | 1,141 | 2,580 | +126% | 0 | 0 | — |
case-09 | pass→pass | 6,672 | 5,034 | -25% | 1 | 1 | 0% | 1,258 | 2,746 | +118% | 0 | 0 | — |
case-10 | pass→pass | 6,022 | 3,892 | -35% | 1 | 1 | 0% | 1,049 | 2,354 | +124% | 0 | 0 | — |
case-11 | pass→pass | 7,267 | 7,365 | +1% | 1 | 1 | 0% | 1,506 | 3,222 | +114% | 0 | 0 | — |
case-12 | fail→pass | 9,278 | 6,486 | -30% | 1 | 1 | 0% | 1,800 | 3,085 | +71% | 0 | 0 | — |
case-13 | pass→pass | 7,313 | 9,653 | +32% | 1 | 1 | 0% | 1,001 | 2,225 | +122% | 0 | 0 | — |
case-14 | pass→pass | 7,519 | 4,558 | -39% | 1 | 1 | 0% | 1,489 | 2,616 | +76% | 0 | 0 | — |
case-15 | pass→pass | 6,077 | 3,475 | -43% | 1 | 1 | 0% | 1,122 | 2,320 | +107% | 0 | 0 | — |
case-16 | pass→pass | 8,026 | 4,895 | -39% | 1 | 1 | 0% | 1,424 | 2,700 | +90% | 0 | 0 | — |
case-17 | pass→pass | 2,431 | 2,090 | -14% | 1 | 1 | 0% | 331 | 2,049 | +519% | 0 | 0 | — |
case-18 | pass→pass | 6,931 | 7,672 | +11% | 1 | 1 | 0% | 1,273 | 3,075 | +142% | 0 | 0 | — |
case-19 | pass→pass | 4,975 | 3,325 | -33% | 1 | 1 | 0% | 874 | 2,314 | +165% | 0 | 0 | — |
case-20 | pass→pass | 7,588 | 5,102 | -33% | 1 | 1 | 0% | 1,357 | 2,780 | +105% | 0 | 0 | — |
case-21 | pass→pass | 5,514 | 3,707 | -33% | 1 | 1 | 0% | 1,020 | 2,458 | +141% | 0 | 0 | — |
case-22 | pass→pass | 6,655 | 1,407 | -79% | 1 | 1 | 0% | 1,215 | 1,967 | +62% | 0 | 0 | — |
case-23 | pass→pass | 7,585 | 5,141 | -32% | 1 | 1 | 0% | 1,386 | 2,662 | +92% | 0 | 0 | — |
case-24 | pass→pass | 6,470 | 2,801 | -57% | 1 | 1 | 0% | 1,220 | 2,288 | +88% | 0 | 0 | — |
case-25 | pass→pass | 8,846 | 8,816 | -0% | 1 | 1 | 0% | 1,676 | 3,477 | +107% | 0 | 0 | — |
case-26 | pass→pass | 15,638 | 14,247 | -9% | 1 | 1 | 0% | 2,667 | 4,286 | +61% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 26 cases were attempted. The headline lift of +8 percentage points is the difference between those two pass rates over the 26 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/2/2026 | -33% |
Other measured skills in the registry, with their headline benchmark lift.