【Godot4】GDExtensionの始め方
0. この記事の内容
大量の計算を行ったり、複雑なアルゴリズムをGodotで行いたい時、GDExtensionでは物足りない場合があります。そんな時はGDExtensionの出番です。エンジンをコンパイルせずともC++やその他言語で処理を書き、Godotで利用することができるのです。しかし、GDExtensionに関する情報(特に日本語)は少なく、なかなかハードルが高いのが現状です。今回GDExtensionを利用する機会があったので、GDExtensionの作り方と流れを備忘録としてまとめてみました。
1. 参考にした記事
-
GDExtension C++ example
- 公式の解説記事です。
-
GDExtensionシンプルに環境構築するよ Pt.1
- とても丁寧に解説されています。私はこの記事のお陰でGDExtensionデビューできました。
-
Godot GDEXTENSION build 環境構築のまとめ(その1)
- かなり踏み込んだ内容まで解説されています。
2. 環境構築
C++でGDExtensionを作成しビルドするには次の3つが必要です。
- MinGW
- Python
- SCons
SConsはビルド処理をPythonで記述できるツールで、MinGWはC++のコンパイルに使用します。
2.1 MinGWを準備する。
MinGWの公式サイトの左からDownload(のページに行き、Mingw-buildsの項目に記載されているGitHubのリポジトリから
x86_64-13.2.0-release-win32-seh-msvcrt-rt_v11-rev0.7z
をダウンロードします。
ダウンロードしたファイルを解凍し、適当なディレクトリに置きます。今回はCドライブ直下にしました。mingw64の中にbinというフォルダがあり、以下のようなパスになっていることを確認します。
C:\mingw64\bin\
次にこのパスを環境変数Path
に追加します。Windowsキーを押した検索欄にenvと入力すると、環境変数の設定画面にすぐ飛べます。便利。
ターミナルでwhere gcc
と入力し、C:\mingw64\bin\
が出力されていればOKです。
2.2 Pythonを準備する
Pythonの公式サイトからダウンロードします。インストーラを使うのが簡単です。インストール時はAdd Python to PATHのチェックボックスを有効にします。インストーラを使うと同時にpipもインストールされます。ターミナルでwhere python
、where pip
と入力し、どちらも正常にパスが表示されればインストール完了です。
2.3 SConsを準備する
ターミナルからpython -m pip install scons
と入力すると、SConsのインストールが始まります。where scons
でscons.exeのパスが表示されれば準備完了です。
3. プロジェクトを作成する
3.1 godot-cppを用意する
GitHubから対象のバージョンを選びダウンロードします。GDExtensionを使うGodotエディタのバージョンと揃えましょう。ダウンロードしたgodot-cpp-godot-◯.◯.◯-stable
(以下godot-cpp
)にはtest
というフォルダがあります。これがGDExtensionのサンプルとなるプロジェクトフォルダで、このtest
フォルダをコピペして編集することで簡単にGDExtensionが作成できます。
3.2 testフォルダの構造を確認する
testフォルダはGDExtension作成時の見本となるフォルダです。この構成を見本にしてオリジナルのGDExtensionプロジェクトを作成します。
test/
├ project/
│ ├ bin/
│ ├ example.gdextension
│ └ その他色々...
├ src/
│ ├ exmample.h
│ ├ exmample.cpp
│ ├ register_types.h
│ └ reister_types.cpp
├ SConstruct
└ その他色々...
実際にGDExtensionを作る際は、example.h
とexample.cpp
が自分の作ったスクリプトに置き換わるイメージです。一方、register_types.h
とregister_types.cpp
とexample.gdextension
、そしてSConstruct
はそのまま利用しますが、一部編集が必要です。
3.3 オリジナルGDExtensionのプロジェクトをつくる
test
フォルダをgodot-cpp
の外の適当なところにコピペし、名前を変更します(今回はmy_gdextension
とします)。場所はどこでも良いですが、
Your folder structure should now look like this:
gdextension_cpp_example/ | +--demo/ # game example/demo to test the extension | +--godot-cpp/ # C++ bindings | +--src/ # source code of the extension we are building
In the src folder, we'll start with creating our header file for the GDExtension node we'll be creating.
とのことです。今回の場合、gdextension_cpp_example
がmy_gdextension
フォルダに相当し、my_gdextension
フォルダの中に、Godotのプロジェクトとgodot-cpp
を入れる感じです。多分。
私は最初よくわからずに、
gdextensions/
├ my_gdextension/
└ godot-cpp/
という構成で初めてしまいましたが、問題ありませんでした。
この記事では公式の推奨する構成を前提とします。
3.4 SConstructを編集する
my_gdextension
のSConstructを開くと上の方に、
env = SConscript("../SConstruct")
と書いてあります。これは、godot-cpp
のSConstructを呼び出す処理で、そのパスを指定すれば良いわけです。今回の場合は
env = SConscript("./godot-cpp/SConstruct")
となります。godot-cpp
の部分は実際のフォルダ名:godot-cpp-godot-◯.◯.◯-stable
に置き換えてください。今回は相対パスで指定していますが、絶対パスでもOKです。
次に必要なライブラリを静的にリンクしておきます。先ほど編集した行の次に
env.Append(
LINKFLAGS=[
"--static",
"-static-libgcc",
"-static-libstdc++",
]
)
を追加します。これをしないとMinGWに依存してしまうので、忘れず追記しましょう。
3.5 .gdextensionを編集する
exampe.gdextensionの中身を覗いてみましょう。
example.gdextension
[configuration]
entry_symbol = "example_library_init"
compatibility_minimum = "4.1"
[libraries]
macos.debug = "res://bin/libgdexample.macos.template_debug.framework"
macos.release = "res://bin/libgdexample.macos.template_release.framework"
windows.debug.x86_32 = "res://bin/libgdexample.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "res://bin/libgdexample.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll"
windows.debug.arm64 = "res://bin/libgdexample.windows.template_debug.arm64.dll"
windows.release.arm64 = "res://bin/libgdexample.windows.template_release.arm64.dll"
linux.debug.x86_32 = "res://bin/libgdexample.linux.template_debug.x86_32.so"
linux.release.x86_32 = "res://bin/libgdexample.linux.template_release.x86_32.so"
linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so"
linux.debug.arm32 = "res://bin/libgdexample.linux.template_debug.arm32.so"
linux.release.arm32 = "res://bin/libgdexample.linux.template_release.arm32.so"
linux.debug.arm64 = "res://bin/libgdexample.linux.template_debug.arm64.so"
linux.release.arm64 = "res://bin/libgdexample.linux.template_release.arm64.so"
linux.debug.rv64 = "res://bin/libgdexample.linux.template_debug.rv64.so"
linux.release.rv64 = "res://bin/libgdexample.linux.template_release.rv64.so"
android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so"
android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so"
android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so"
android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so"
ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework"
ios.release = "res://bin/libgdexample.ios.template_release.xcframework"
web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm"
web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm"
[dependencies]
ios.debug = {
"res://bin/libgodot-cpp.ios.template_debug.xcframework": ""
}
ios.release = {
"res://bin/libgodot-cpp.ios.template_release.xcframework": ""
}
entry_symbol = "example_library_init"
ではregister_types.cpp
のexample_library_init
という関数を登録しています。これによりGDExtensionのクラスをGodotに登録しています。
[libraries]
の項目では読み込むdllのパスを指定しています。今回はWindows環境を想定しているため、
windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll"
以外は消してしまって大丈夫です。dllの名前やパスが異なる場合は編集してください。
4. オリジナルGDExtension作成の流れ
ここまで来たら準備完了です。
-
src
フォルダにソースファイルを作成する -
register_types.cpp
から作成したクラスを登録する - コマンド
scons use_mingw=yes
でビルド -
my_gdextension/project/bin/
のdllファイルをGodotのプロジェクトにコピペする(慣習的にres://bin/
に置く) -
my_gdextension/project/example.gdextension
を同じフォルダに置く
Godotエディタを再起動して、追加したクラスが認識されていれば成功です。Godot4.2ではGDExtensionのホットリロードに対応しているそうですが、私の場合は再起動が必要でした(?)。
Discussion