作为GDScript开发者的C#体验!其一
2025-04-09
本文将记录我使用C#的过程中踩下的各种坑。鄙人用过几年gdscript, 对这门灵活的语言深表赞赏。但出于工程需求,我也有了想要尝试C#的想法,故有了此文。倘若我折腾的经历能帮到你,那也是很好的。
下载引擎和Dotnet!
官网上提供了Dotnet版本的godot下载。只需下载即可。简单。
对了,还请顺带确保你安装了C#相关套件——我是说,一个成熟的IDE(比如Visual Studio, VSCode, 或者Rider)。正好赶上Rider允许非商业免费使用,考虑到这个游戏是个测试工程,我就打算用rider来写了。据说rider用起来还挺傻瓜的?
记得到官网上寻找Dotnet 8.x的SDK!目前最新版本的戈多已经要求使用至少8.x的dotnet了。不知道是好事还是坏事?
开始表演:开启C#项目?
随便创建一个项目,找一个节点,给它赋予C#脚本,戈多就会为你的项目生成“解决方案”?
我不知道所谓“解决方案”是什么东西。在一番询问AI后,得到了以下结果:
1. .csproj
文件(C# 项目文件)
-
是什么:
一个 XML 格式的文件,定义了一个 C# 项目的结构和依赖项(类似 Java 中的pom.xml
或build.gradle
)。
Godot 会为你的游戏生成一个.csproj
文件,例如YourGame.csproj
。 -
作用:
- 指定项目使用的 .NET 版本(如
.NET 6
/7
/8
。最新版戈多要求8.x起步。) - 列出需要编译的 C# 文件(
<Compile Include="Scripts/Player.cs" />
) - 声明 NuGet 包依赖(如
<PackageReference Include="ImGui.NET" />
) - 配置 Godot 特有的设置(如
<GodotProjectRoot>..</GodotProjectRoot>
)
- 指定项目使用的 .NET 版本(如
-
Godot 中的示例:
<Project Sdk="Godot.NET.Sdk/4.1.3"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> </PropertyGroup> <ItemGroup> <Compile Include="Scripts/Player.cs" /> </ItemGroup> </Project>
2. .sln
文件(解决方案文件)
-
是什么:
一个文本文件,用于组织多个.csproj
项目(类似 Java IDE 中的“Workspace”)。
Godot 生成的解决方案默认只包含你的游戏项目(例如YourGame.sln
)。 -
作用:
- 允许在 IDE(如 Visual Studio、Rider)中同时打开多个相关项目
- 管理项目间的引用关系(比如依赖一个共享库)
- 提供构建配置的全局设置
-
Godot 生成的示例:
Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YourGame", "YourGame.csproj", "{...}" EndProject
来安装外部包吧。但立刻遇到麻烦了?!
使用GDS期间,我非常喜欢ImGui这个插件。它似乎也有Dotnet版本的支持。二话不说,立刻安排上。
随便创建一个小场景,随便赋予个初始默认C#脚本,点击“运行”,引擎会自动构建工程。。。
比起纯GDScript, dotnet版本要等上好几秒才能等到游戏显示窗口。嗯,为了安全性和可维护性,这点取舍是值得的。
嗯.. 不对。。这是?
啥??
GDS这边则是只有用到的脚本才会参与游戏,即使你写了个语法完全狗屁不通的脚本,只要你只是把它放在某个目录里不动它也不调用/加载/引用它,它就不会给你的游戏带来错误。
看起来C#比GDS要严格多了呢。似乎 所有C#文件都会被纳入编译范围
。这什么意思呢?这意味着,你在项目里拉的每一行C#💩,最终都逃不了编译器的法眼。
很显然我们刚刚安装的插件出了问题,导致编译器报错了?
啊。回过头来再看看我们的插件说明?
https://github.com/pkdawson/imgui-godot?tab=readme-ov-file#getting-started-c
啊,原来如此。我们需要用Nuget来安装包: ImGui.NET
。
等会,Nuget又是什么东西??
那Nuget是什么东西?Asset Lib?
其实,NuGet 就像 Godot 的 AssetLib,但专门管 C# 的代码库(比如 ImGui.NET
)。当你写 using SomeLibrary;
时,NuGet 就是背后帮你下载这个库的工具。
让我们安装 ImGui.NET吧。 首先在项目的根目录下打开终端,输入:
dotnet add package ImGui.NET
如果你此时注意csproj文件,你会注意多了这么一行:
<PackageReference Include="ImGui.NET" Version="x.x.x" />
这就意味着,Dotnet在你的游戏项目里,成功安装了名为ImGui.NET的包。后续使用dotnet构建游戏时,会将这个包也一并纳入你的游戏,你可以在你的代码的任何地方使用它!
相较于戈多的Asset Lib, dotnet的这套管理策略似乎,更“保守”?或者说,更“安全”?一旦开发者数量多起来,这种死板的方式就成了保证项目不出问题的保障?谁知道呢?
"UnSafe Code"? 这又是啥?
好了,我们现在安装了ImGui.Net了。接下来总算可以Build了吧?
等等。。
“Allow Unsafe Blocks”...
说到了这里,咱们就不得不了解下Unsafe是什么了。
字面意思:代码可以绕过 .NET 的安全检查,直接操作指针和内存地址(类似 C/C++)。
安全代码(默认) | 不安全代码(unsafe ) |
---|---|
内存完全由 .NET 运行时管理 | 可以手动搞指针、内存地址 |
无法直接调用原生库 | 能和 C/C++ 库无缝互操作 |
性能稍低(有安全检查开销) | 性能更高(但可能炸💥) |
ImGui.NET
底层需要和原生 C++ 版的 Dear ImGui 交互,必须通过指针传递数据,所以这种“不太安全”的代码,其实是必要的。倒不如说,如果想调用原生库,就必须使用不安全代码。
那具体怎么做?
其实,只要编辑项目的 .csproj
文件,在 <PropertyGroup>
中添加:
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
即可。
编译通过,搞定!
(嘛,虽说还是有些warning的,又装了俩插件,就当不存在吧。)