mcpField
G
godot-csharp

godot-csharp

github.com/gamedev-skills开发5.4k6.5k 次安装今天更新
代码仓库

关于 godot-csharp

godot-csharp 是使用 C# 和 .NET 8 编写 Godot 4.7 游戏代码的技能,介绍节点脚本、生命周期、导出属性、信号、场景实例化及与 GDScript 的交互。

主要功能

  1. 01C# 节点脚本与生命周期方法
  2. 02通过 [Export] 暴露检查器字段
  3. 03将信号用作 C# 事件
  4. 04使用 PackedScene 实例化场景
  5. 05调用和访问 GDScript 节点

适用场景

  1. 01用 C# 编写 Godot 游戏逻辑
  2. 02在检查器中公开可调参数
  3. 03将 C# 代码连接到信号
  4. 04与 GDScript 脚本互操作

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill godot-csharp

安装后在 Claude Code 中输入/godot-csharp确认已加载。

附带文件references/csharp-setup-and-interop.md

详细介绍

Godot C# / .NET(4.x)

使用 C# 编写 Godot 游戏代码:节点子类、引擎生命周期、导出、作为事件的信号,以及 GDScript 互操作。目标版本为 Godot 4.7(.NET / C#) 和 .NET 8。

适用场景

  • 使用 C#(.cs + .csproj)编写 Godot 游戏脚本、将 GDScript 习惯写法转换为 C#、公开 [Export] 字段,或连接 [Signal] 委托并使用 GetNode 时使用。

不适用场景: GDScript 专属语法 → godot-gdscript;与语言无关的引擎概念(场景、物理、动画)→ 相应的 godot-* 技能。你需要安装 Godot .NET 构建版本和 .NET SDK;标准构建版本无法运行 C#。

核心工作流

  1. 使用 Godot .NET 编辑器构建版本并安装匹配的 .NET 8 SDK。创建第一个 C# 脚本时会生成 .csproj/.sln。使用编辑器或 dotnet build 进行构建。
  2. 每个节点脚本都是扩展 Godot 类型的 partial 类(源生成器依赖 partial)。文件名应与节点脚本类名一致。
  3. 使用 PascalCase 重写生命周期方法,并将 delta 参数设为 double:_Ready()、_Process(double delta)、_PhysicsProcess(double delta)。
  4. 使用 [Export] 公开可调参数;它们会像 GDScript 的 @export 一样显示在检查器中。
  5. 将信号声明为 [Signal] 委托,并命名为 XxxEventHandler;使用 EmitSignal(SignalName.Xxx, ...) 发出信号,并通过生成的 C# event 订阅。
  6. 使用 GetNode<T>("Path")(或 %Unique)获取节点,并在需要时使用 Call/Get/Set 调用 GDScript。

模式

1. 节点脚本:生命周期、[Export]、GetNode
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. 将信号用作 C# 事件
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. 在 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. 与 GDScript 节点互操作
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");

易踩坑

  • 忘记 partial。 没有 partial,Godot 源生成器就无法扩展该类,[Export]/[Signal] 会出错,且构建错误信息难以理解。
  • 方法大小写或签名错误。 C# 重写方法必须是 _Ready、_Process(double)、_PhysicsProcess(double),采用 PascalCase,delta 类型为 double(GDScript 使用 snake_case 和 float)。名称不匹配时,方法不会被调用。
  • [Signal] 委托命名。 名称必须以 EventHandler 结尾;引擎会使用去掉该后缀后的名称公开信号,并生成 SignalName.X 和一个 C# event。
  • GD.Print 与 Console.WriteLine。 使用 GD.Print/GD.PrintErr 将输出写入 Godot 输出面板;Console 输出可能不会显示。
  • 值类型结构体。 Vector2、Color、Transform2D 都是结构体——应修改局部副本(var v = Velocity; v.X = ...; Velocity = v;);直接编辑 Velocity.X 无法编译或持久生效。
  • 需要 .NET 构建版本和 SDK。 非 .NET 编辑器无法运行 C#;.NET SDK 缺失或版本不匹配会导致构建失败。Godot 4.7 的目标为 .NET 8;请查看当前平台的导出说明,因为 Android 和其他 AOT 目标可能需要更新的 SDK 工具。
  • QueueFree() 与 Free()——规则与 GDScript 相同;优先使用 QueueFree()。释放对象后继续使用会抛出 ObjectDisposedException。
  • .NET 在某些平台上的导出方式有所不同(例如 Web/移动平台可能需要额外步骤);请查看目标平台的 .NET 导出说明。

参考资料

  • 关于导出属性的不同形式([ExportGroup]、范围、类型化数组)、使用 await ToSignal(...) 的异步操作、Godot.Collections 与 System 集合、C# 中的自定义资源,以及项目/构建设置,请阅读 references/csharp-setup-and-interop.md。

相关技能

  • godot-gdscript — 这些模式对应的 GDScript 写法。
  • godot-signals-groups — 信号/事件架构(与语言无关)。
  • godot-resources — 数据资源;C# 的 [Export] + Resource 模式。
  • unity-csharp-scripting — Unity 中的 C#,适用于从 Unity 转来的开发者。

评论

支持 Markdown