Skip to content
Development
Skill

/csharp-godot

Use when working with C# in Godot — conventions, GodotSharp API differences from GDScript, project setup, and interop

From plugin
godot-prompter
54157 skills9 agents1 hook
Install
$ npx -y skills add jame581/GodotPrompter --skill csharp-godot --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/csharp-godot

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when working with C# in Godot — conventions, GodotSharp API differences from GDScript, project setup, and interop

SKILL.md

csharp-godot.SKILL.md
name: csharp-godot
description: Use when working with C# in Godot — conventions, GodotSharp API differences from GDScript, project setup, and interop

C# in Godot 4.3+

This skill covers C#-specific conventions, API differences from GDScript, project setup, and interop patterns. All examples are C# only. Target Godot 4.3+ with the GodotSharp NuGet package.

> **Related skills:** **csharp-signals** for C# signal patterns, **godot-project-setup** for C# project scaffolding, **godot-testing** for C# testing with gdUnit4, **gdextension** for native C++ when C# is not enough, **multithreading** for C# concurrency.

---

1. C# vs GDScript Syntax Comparison

| GDScript | C# Equivalent | Notes | |---|---|---| | `var x = 5` | `var x = 5;` or typed `int x = 5;` | C# `var` infers type at compile time | | `func MyMethod() -> void:` | `public void MyMethod() { }` | Methods are PascalCase in C# | | `signal health_changed(amount: int)` | `[Signal] delegate void HealthChangedEventHandler(int amount);` | Must use `EventHandler` suffix | | `@export var speed: float = 100.0` | `[Export] public float Speed { get; set; } = 100f;` | PascalCase, property syntax | | `@onready var label = $Label` | `private Label _label;` + `_label = GetNode<Label>("Label");` in `_Ready()` | No `@onready` equivalent; use `_Ready()` | | `match value:` | `switch (value) { case X: break; }` | C# switch also supports pattern matching | | `class_name MyClass` | `[GlobalClass] public partial class MyClass : GodotObject { }` | Requires `[GlobalClass]` attribute | | `extends Node` | `public partial class MyScript : Node { }` | Inheritance via `:` | | `preload("res://scene.tscn")` | `GD.Load<PackedScene>("res://scene.tscn")` | Loaded at runtime, not compile time | | `push_error("msg")` | `GD.PushError("msg");` | Prints to Godot error log | | `print("msg")` | `GD.Print("msg");` | Also: `GD.PrintS()`, `GD.PrintT()` | | `node is CharacterBody2D` | `node is CharacterBody2D` | Same keyword, same semantics | | `node as CharacterBody2D` | `node as CharacterBody2D` | Returns `null` on failure in both | | `await signal_name` | `await ToSignal(source, SignalName.X);` | Must use `ToSignal()` wrapper | | `Array` | `Godot.Collections.Array` | Not `System.Collections.Generic.List<T>` | | `Dictionary` | `Godot.Collections.Dictionary` | Not `System.Collections.Generic.Dictionary<K,V>` |

---

2. Project Setup

.csproj and Solution

Godot auto-generates the `.csproj` when you create the first C# script via **Script > New Script > C#**. Do not edit the generated file structure manually — let the editor manage it.

MyProject/
├── MyProject.csproj          # Auto-generated, edit only for NuGet packages
├── MyProject.sln             # Auto-generated solution file
├── project.godot
└── scripts/
    └── Player.cs

NuGet Packages

Add packages in `MyProject.csproj` inside `<ItemGroup>`:

<Project Sdk="Godot.NET.Sdk/4.3.0">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <ItemGroup>
    <!-- Example: add a third-party NuGet package -->
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>
</Project>

Run `dotnet restore` or let the IDE restore automatically after editing.

Godot.NET Preview Bindings (Godot 4.7+)

Godot 4.7's `Godot.NET.Sdk` accepts an opt-in MSBuild property that switches the project from the classic GodotSharp bindings to the preview Godot.NET bindings (the `Godot.Bindings` assembly instead of `GodotSharp`):

<PropertyGroup>
  <EnableGodotDotNetPreview>true</EnableGodotDotNetPreview>
</PropertyGroup>

The preview bindings are experimental — leave the property unset for production projects. See [GH-118001](https://github.com/godotengine/godot/pull/118001).

IDE Setup

| IDE | Setup Required | Notes | |---|---|---| | JetBrains Rider | Install Godot plugin (bundled in Rider 2023.3+) | Best Godot C# support; debugger works out of the box | | VS Code | Install **C# Dev Kit** + **Godot Tools** extensions | Requires `launch.json` for debugger attachment | | Visual Studio | Install **Godot Visual Studio** extension | Windows only; debugger via `Tools > Attach to Process` |

For all IDEs, open the `.sln` file (not just a folder) to get full solution resolution.

---

3. The `partial class` Requirement

Every class that extends a Godot type **must** be declared `partial`. This is not optional.

Why

Godot uses C# source generators to emit the signal registration, property binding, and RPC code alongside your class. Source generators require `partial` to inject into the same class declaration.

Error When Forgotten

Error CS0260: Missing partial modifier on declaration of type 'Player';
another partial declaration of this type exists.

Or the class compiles but signals and `[Export]` properties silently fail to register.

Rule

// CORRECT
public partial class Player : CharacterBody2D { }

// WRONG — will cause source generator errors
public class Player : CharacterBody2D { }

This applies to every class in the inheritance chain that extends a Godot type, including intermediate base classes.

---

4. Naming Conventions

| Element | Convention | Example | |---|---|---| | Methods | PascalCase | `public void TakeDamage(int amount)` | | Properties | PascalCase | `public float MaxHealth { get; set; }` | | Signals (delegate) | PascalCase + `EventHandler` suffix | `HealthChangedEventHandler` | | `[Export]` properties | PascalCase | `[Export] public float Speed { get; set; }` | | Private fields | `_camelCase` with underscore prefix | `private float _currentSpeed;` | | Local variables | camelCase | `var newPosition = ...` | | Parameters | camelCase | `void SetHealth(int newHealth)` | | Godot API names | Match Godot's PascalCase exactly | `GlobalPosition` not `global_position` | | Enums | PascalCase type, PascalCase member

Read more
Ships withgodot-prompter

Agentic skills framework for Godot 4.x game development. Gives AI coding agents domain-specific expertise for GDScript and C# projects.

Get the whole plugin