/csharp-godot
Use when working with C# in Godot — conventions, GodotSharp API differences from GDScript, project setup, and interop
$ npx -y skills add jame581/GodotPrompter --skill csharp-godot --agent claude-codeHow 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.mdname: 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.csNuGet 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
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.csNuGet 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
Agentic skills framework for Godot 4.x game development. Gives AI coding agents domain-specific expertise for GDScript and C# projects.
Other skills on godot-prompter.
- /authoring-godot-prompter-skills
Use when writing or editing a SKILL.md or an agent definition in this repo — required frontmatter, section ordering, and the GDScript-then-C# example convention.
Open skill - /releasing-godot-prompter
Use when cutting a GodotPrompter release or bumping its version — the version-bump sequence, tag-triggered workflow, and the marketplace manifests that must follow.
Open skill - /2d-essentials
Use when working with 2D-specific systems — TileMaps, parallax scrolling, 2D lights and shadows, canvas layers, particles 2D, custom drawing, and 2D meshes in Godot 4.3+
Open skill - /3d-essentials
Use when working with 3D-specific systems — materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion culling, and decals in Godot 4.3+
Open skill - /ability-system
Use when building character abilities — Resource-based abilities with cost/cooldown/cast, buffs/debuffs, stat modifiers, gameplay tags, and HUD binding
Open skill - /addon-development
Use when creating Godot editor plugins — EditorPlugin, @tool scripts, custom inspectors, and dock panels
Open skill

