TL;DR
ファイル名とクラス名を一致させよう
概要
C#を使ってGodotのチュートリアルを進めていたのですが、地味に分かりづらいポイントがあったので解説していきます。
その1: macOSを使う場合はHomebrew経由で.NETをインストールする
初め、Godotの公式ドキュメント通りにMicrosoftの公式のインストーラーから.NETをインストールしたのですが、なぜかターミナルでdotnet
コマンドを実行できませんでした。
.zshrc
を編集してパスを通しても全く反応せず……。
諦めてbrew経由で.NETをインストールしたところ、難なくdotnet
コマンドが実行できるようになりました。
そのため、macOSを利用している方は、brew経由で.NETをインストールすることをオススメします。
formulae.brew.sh
dotnet — Homebrew Formulae
brew install --cask dotnet
その2: ファイル名とクラス名を一致させよう
これが一番詰まったポイントでした。
docs.godotengine.org
初めてのスクリプト作成 — Godot Engine (4.x)の日本語のドキュメント
ドキュメントには次のように書いてあります。
The Script workspace should appear with your new sprite_2d.gd file open and the following line of code:
これに従って何も考えずにファイルを作ると、sprite_2d.cs
を作成することになります。
さて、この状態でこのページの一番最後のスクリプトを動かすと、Godotくんの画像が動きません。
エディタの画面を開くと次のように表示されます。
/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:561 - Missing class qualified name for reloading script
また、Debuggerにはこのように表示されます。
E 0:00:00:0373 can_instantiate: Cannot instance script because the associated class could not be found. Script: 'res://sprite_2d.cs'. Make sure the script exists and contains a class definition with a name that matches the filename of the script exactly (it's case-sensitive).
<C++ Error> Method/function failed. Returning: false
<C++ Source> modules/mono/csharp_script.cpp:2417 @ can_instantiate()
どういうことかというと、サンプルコード内のMySprite2D
が原因でエラーが発生しています。
この部分を最初に作成したファイル名、すなわちsprite_2d
にしなければなりません。ファイル名とクラス名を合わせる必要があります。
Before
public partial class MySprite2D : Sprite2D
After
public partial class sprite_2d : Sprite2D
「Make sure the script exists and contains a class definition with a name that matches the filename of the script exactly (it's case-sensitive).」とはそれを意味しているのです。
具体的にどうするのが良い?
例えば上記の例でsprite_2d.cs
をSprite2D.cs
としてファイルを作成すると、既存のクラス名と衝突してエラーが発生します。
public partial class Sprite2D : Sprite2D
となり、明らかにおかしいことがわかります。
しかし、C#ではスネークケースを使用することはあまり無いらしいです。
そのため次のどちらかにする方が良いでしょう。
- 頭に
My
を付けて、ファイル作成時にMySprite2D.cs
と命名し、クラス名もclass MySprite2D
とする
- 独自のクラス名を考えて、その名前でファイル名とクラス名を揃える
- 今回の場合だと
Rotate.cs
とclass Rotate
とか
その3: ターミナル出力
ドキュメントだと分かりにくいですが、ターミナルにHello, world
を出力するためのコード全体はこんな感じです。
コンストラクタを呼んだときに出力しています。
using Godot;
public partial class MySprite2D : Sprite2D
{
public MySprite2D(){
GD.Print("Hello, world!");
}
}
他にもこんな書き方ができます。
using Godot;
public partial class MySprite2D : Sprite2D
{
public override void _Ready()
{
GD.Print("Hello, world!");
}
}
このあたりの説明は公式ドキュメントの次の箇所に詳しく書かれています。
docs.godotengine.org
C# の基本 — Godot Engine (4.x)の日本語のドキュメント
まとめ
いかがでしたでしょうか?(よくネットで見かける締め方)
C#で開発をおこなう場合は、色々注意すべきポイントがあることを確認できたと思います。特にGodotの開発においてはファイル名とクラス名の一致が重要になります。
もし同じエラーに苦しんでいる方はこの記事を参考にしてみてください!