PluginBench
Skill
Pass
Audit score 90

godot-csharp

gamedev-skills/awesome-gamedev-agent-skills

Write Godot 4.7 game code in C# with type-safe nodes, signals as events, and GDScript interop.

What is godot-csharp?

Use C# and .NET 8 to script Godot 4.7 games with partial node classes, PascalCase lifecycle methods, [Export] fields, and [Signal] delegates. Install when you need to write game logic in C# instead of GDScript, convert GDScript patterns to C#, or integrate C# with existing GDScript nodes.

  • Override Godot lifecycle methods (_Ready, _Process, _PhysicsProcess) in PascalCase with type-safe signatures
  • Expose Inspector-editable fields using [Export] attributes
  • Declare and emit signals as C# events with [Signal] delegates and type-safe SignalName constants
  • Use GetNode<T>("Path") for type-safe node lookup and casting
  • Instance PackedScene objects with typed Instantiate<T>() calls
  • Call GDScript methods and access properties dynamically via Call/Get/Set for interop

How to install godot-csharp

npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill godot-csharp
Prerequisites
  • Godot 4.7 .NET build (not the standard build)
  • The .NET 8 SDK installed and matching your Godot version
  • A Godot project with C# enabled (creates .csproj/.sln on first C# script)
Claude Code
Cursor
Windsurf
Cline

How to use godot-csharp

  1. 1.Install the Godot 4.7 .NET editor build and .NET 8 SDK for your platform
  2. 2.Create a new C# script in the Godot editor, which auto-generates the .csproj and .sln files
  3. 3.Write node classes as `public partial class YourNode : NodeType` extending the appropriate Godot node type
  4. 4.Override lifecycle methods in PascalCase: _Ready(), _Process(double delta), _PhysicsProcess(double delta)
  5. 5.Use [Export] public fields for Inspector-editable parameters and [Signal] public delegates for events
  6. 6.Call GetNode<T>("NodePath") to retrieve child nodes with type safety, or use % for unique names
  7. 7.Build with `dotnet build` or the Godot editor, then run the game to test

Use cases

Good for
  • Writing a complete game in C# with Godot's .NET build instead of GDScript
  • Converting an existing GDScript project to C# for better IDE support and type safety
  • Building a player controller with [Export] speed/jump parameters editable in the Inspector
  • Wiring game events (health changes, score updates) as C# events between nodes
  • Spawning bullets or enemies from a C# spawner that loads and instances PackedScene files
Who it's for
  • C# developers new to Godot who want to use their primary language
  • Game developers migrating from Unity to Godot
  • Teams preferring static typing and IDE tooling over GDScript's dynamic approach
  • Projects mixing C# and GDScript that need interop patterns

godot-csharp FAQ

Do I need the .NET build of Godot or can I use the standard build?

You must use the Godot 4.7 .NET build; the standard build cannot execute C# scripts. If you try to use C# with the standard build, you will get build errors.

Why does my [Export] field or [Signal] not work?

Your class must be declared `partial` so the Godot source generator can extend it. Without `partial`, the generator cannot inject the required code and you will see confusing build errors.

How do I override lifecycle methods correctly?

Use PascalCase names (_Ready, _Process, _PhysicsProcess) with the exact signature: _Process and _PhysicsProcess take a `double delta` parameter, not `float`. Mismatched names or signatures will not be called.

How do I connect to signals from GDScript nodes in my C# code?

Use `GetNode("path").Connect("signal_name", Callable.From(MyMethod))` to dynamically connect to GDScript signals, or call GDScript methods with `GetNode("path").Call("method_name", args)`.

Can I mutate Vector2 and other struct properties directly?

No; Vector2, Color, Transform2D, and other Godot structs are value types. You must assign to a local copy, modify it, then reassign: `var v = Velocity; v.X = 10; Velocity = v;`

Full instructions (SKILL.md)

Source of truth, from gamedev-skills/awesome-gamedev-agent-skills.


name: godot-csharp description: > Use C#/.NET in Godot 4.7: partial classes extending nodes, the PascalCase lifecycle (_Ready/_Process/_PhysicsProcess), [Export] fields, [Signal] delegates as C# events, type-safe node lookup, 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.

Godot C# / .NET (4.x)

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.

When to use

  • Use when scripting a Godot game in C# (.cs + .csproj), translating GDScript idioms to 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#.

Core workflow

  1. Use the Godot .NET editor build and install the matching .NET 8 SDK. Creating the first C# script generates a .csproj/.sln. Build with the editor or dotnet build.
  2. Every node script is a partial class extending a Godot type (the source generator relies on partial). The file/class name should match the node script.
  3. Override lifecycle methods in PascalCase with double delta: _Ready(), _Process(double delta), _PhysicsProcess(double delta).
  4. Expose tunables with [Export]; they show in the Inspector like GDScript @export.
  5. Declare signals as [Signal] delegates named XxxEventHandler; emit with EmitSignal(SignalName.Xxx, ...) and subscribe with the generated C# event.
  6. Get nodes with GetNode<T>("Path") (or %Unique), and call into GDScript with Call/Get/Set when needed.

Patterns

1. A node script: lifecycle, [Export], GetNode<T>

using 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
    }
}

2. Signals as C# events

using 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}");
}

3. Instancing a scene in C#

public 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);
    }
}

4. Interop with GDScript nodes

public 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");

Pitfalls

  • Forgetting partial. Without partial, the Godot source generator can't extend the class and [Export]/[Signal] break with confusing build errors.
  • Wrong method case/signature. C# overrides are _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 the signal 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 Godot output panel; Console output may not appear.
  • Value-type structs. Vector2, Color, Transform2D are structs — mutate a local copy (var v = Velocity; v.X = ...; Velocity = v;); editing Velocity.X directly won't compile/persist.
  • Needs the .NET build + SDK. The non-.NET editor can't run C#; mismatched/missing .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(). Disposed objects throw ObjectDisposedException if used after freeing.
  • Export to some platforms differs for .NET (e.g. extra steps for web/mobile); check the .NET export notes for your target.

References

  • For export attribute variants ([ExportGroup], ranges, typed arrays), async with await ToSignal(...), Godot.Collections vs System collections, custom Resources in C#, and project/build setup, read references/csharp-setup-and-interop.md.

Related skills

  • 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.