プログラミング
Godot で C++ ライブラリを使用する
Using any C++ library in Godot (blog.conan.io)
要約
Godot エンジンは、GDScript でゲーム開発を行うのが一般的ですが、既存の C/C++ ライブラリを利用したい場合、GDExtension と公式 C++ バインディングである godot-cpp を通じてネイティブコードを統合できます。この記事では、Godot の C++ 拡張機能の仕組みを解説し、特に Conan と godot-cpp 10 を使用して、flecs のようなライブラリを Godot プロジェクトに組み込む方法を実例を交えて紹介します。これにより、プラットフォームごとのライブラリのコンパイルと依存関係管理が効率化されます。
全文翻訳
Godot は、ここ数年で最も人気のあるゲームエンジンの1つになりました。無料、MIT ライセンスの下でオープンソース、そして数分でダウンロードして使い始められるほど小さいです。ほとんどの Godot ゲームは、エンジンの独自のスクリプト言語である GDScript で書かれています。しかし、多くのプロジェクトでは、シミュレーションライブラリ、データベース、ネットワーキングプロトコル、機械学習ランタイムなど、すでに C または C++ ライブラリとして存在するものが sooner or later 必要になります。GDScript はネイティブコードを呼び出すことはできませんが、Godot は GDExtension を通じてそれをロードでき、公式の C++ バインディングである godot-cpp を使用すると、そのコードを通常のエンジンクラスとして公開できます。C++ コードを書くのは簡単な部分です。難しいのはビルドです: godot-cpp はあなたの Godot バージョンと一致する必要があり、追加する各ライブラリは、あなたが配布する各プラットフォーム用にコンパイルする必要があります。この記事では、Godot の簡単な紹介、C++ 拡張機能の仕組みの説明、そして Conan と godot-cpp 10 を使用して C++ ライブラリを Godot ゲームに組み込む方法を示します。例として、Entity Component System ライブラリである flecs を使用して、Godot シーン内で 100,000 個のパーティクルをシミュレートします。
Godot の簡単な紹介
Godot は、2D および 3D ゲームのための汎用エンジンです。Godot プロジェクトのすべては、2つの概念から構築されます: ノードは基本的な構成要素です。各ノードには、タイプ (Sprite2D, Camera3D, AudioStreamPlayer, Timer…)、インスペクターで編集できるプロパティのセット、そしてゲームループ中にエンジンが呼び出す _ready() や _process() のようなコールバックがあります。シーンは、ディスクに .tscn ファイルとして保存されたノードのツリーです。シーンはキャラクター、メニュー、または完全なレベルになり得、シーンは他のシーン内にインスタンス化できます。ビヘイビアは通常、ノードにスクリプトをアタッチすることによって追加されます。GDScript は Python に似た言語で、エンジン用に設計されており、コンパイルステップなしで変更がすぐに表示されるため、ゲームプレイロジックに最適です。C++ 開発者にとって Godot が興味深いのは、エンジン自体が C++ で書かれており、再コンパイルなしで C++ で書かれた拡張機能をロードできることです。これらの拡張機能から来るクラスは、通常のエンジンクラスになります: エディターで組み込みノードの隣に表示され、インスペクターにプロパティが表示され、GDScript は他のノードのように使用できます。次のセクションでは、これらの拡張機能がどのように機能するかを説明します。
C++ による Godot の拡張
Godot に C++ コードを追加するには 2 つの方法があります:
エンジンモジュールは、エンジン自体にコンパイルされます。内部へのフルアクセス権がありますが、Godot の独自のコピー(エディターと各プラットフォームのエクスポートテンプレートを含む)をビルドして配布する必要があります。
GDExtension は、実行時に共有ライブラリ (.dll, .so, .dylib、または Web 上では .wasm) を公式の、変更されていない Godot ビルドにロードします。エンジンは、安定した C インターフェースを通じてライブラリと通信します。GDExtension はほとんどのプロジェクトで推奨されるアプローチであり、多くの人気のあるプラグインが今日配布されている方法です。C インターフェースは直接使用するには冗長であるため、Godot チームは godot-cpp を維持しています。これは、エンジン内部で使用されている API に非常に近い API でそれをラップする C++ ライブラリです。Node2D, Sprite2D, Input のような各エンジンクラスに対して C++ クラスを提供します。あなた自身のクラスは、これらのクラスから派生する通常の C++ コードです。godot-cpp で書かれたノードは次のようになります:
#include <godot_cpp/classes/node2d.hpp>
namespace godot {
class MyNode : public Node2D {
GDCLASS(MyNode, Node2D)
protected:
static void _bind_methods() {}
public:
void _process(double p_delta) override {
// 毎フレーム実行される
}
};
} // namespace godot
バージョン 10.0 以降、単一の godot-cpp リリースは、4.3 以降の任意の Godot バージョンで動作します。api_version ビルドオプションで 1 つを選択すると、godot-cpp はそのバージョンの API から C++ クラスを生成します。Godot 4.3 用にビルドされた拡張機能は、新しいバージョンでも動作しますが、古いバージョンでは動作しません。そのため、通常はサポートしたい最も古い Godot バージョンを選択します。
ビルドターゲットとフィーチャータグ
何かをビルドする前に知っておくべきもう 1 つの概念があります。godot-cpp は、ライブラリをロードする Godot ビルドの名前にちなんで名付けられた 3 つのターゲットのいずれかにコンパイルされます:
template_debug: デフォルト。DEBUG_ENABLED 定義を通じてデバッグチェックを有効にします。このライブラリはエディターとデバッグエクスポートによってロードされます。
template_release: リリースエクスポート用で、デバッグチェックは削除されます。
editor: エディターのみによってロードされるライブラリ用です。
Godot がどのライブラリをロードするかは、小さな .gdextension ファイルによって実行時に決定されます。これはフィーチャータグをライブラリパスにマッピングします。debug タグはエディターとデバッグエクスポートに一致し、release タグはリリースエクスポートに一致します:
[configuration]
entry_symbol = "gdexample_library_init"
compatibility_minimum = "4.7"
[libraries]
macos.debug = "res://bin/libgdexample.template_debug.dylib"
macos.release = "res://bin/libgdexample.template_release.dylib"
linux.debug = "res://bin/libgdexample.template_debug.so"
linux.release = "res://bin/libgdexample.template_release.so"
windows.debug = "res://bin/libgdexample.template_debug.dll"
windows.release = "res://bin/libgdexample.template_release.dll"
通常のワークフロー
Godot のドキュメントでは、godot-cpp を git サブモジュールとしてリポジトリに追加し、SCons を使用してライブラリと一緒にビルドすることを推奨しています。これは最初の拡張機能にはうまく機能しますが、各プロジェクトは各ターゲット、プラットフォーム、アーキテクチャ用に独自の godot-cpp をコンパイルし、ラップするサードパーティライブラリ(物理エンジンや機械学習ランタイムなど)は、Godot がエクスポートする各プラットフォームに合わせてベンダー化され、フラグ付きでビルドする必要があります。これらは両方とも、Conan が解決するために構築された問題の種類です。
Conan による依存関係の管理
ConanCenter の godot-cpp レシピにより、godot-cpp は通常のパッケージになります。上記で議論された 2 つのパラメータは Conan オプションです:
api_version: バインディングがターゲットとする Godot API バージョン (4.3 から 4.7、デフォルト)。
target: template_debug (デフォルト)、template_release、または editor。
各組み合わせは一度だけビルドされ、各プロジェクトがそれを必要とするたびに再利用されます。拡張機能ごとにコンパイルされるのではなく。あなたの GDExtension は、単なる依存関係を持つ別の C++ プロジェクトになります。ConanCenter の 1,900 以上のライブラリのいずれか、または Conan レシピで自分でパッケージ化したライブラリを godot-cpp の隣に追加でき、Conan はターゲットとする各プラットフォームに対してそれらをすべて一貫してビルドします。
実践例: 100,000 個のパーティクルの群れ
これが実際にどのように機能するかを示すために、新しい Swarm ノードを登録する GDExtension を作成します。これは、マウスカーソルから逃げ、ウィンドウの端で跳ね返る 100,000 個のパーティクルをシミュレートし、それらすべてを Godot シーンに描画します。シミュレーションは、C および C++ 用の Entity Component System (ECS) ライブラリである flecs で実行されます。ECS では、エンティティはプレーンな ID であり、コンポーネントはそれらにアタッチされたプレーンなデータ構造であり、システムは特定のコンポーネントセットを持つすべてのエンティティに対して実行される関数です。同じタイプのコンポーネントはメモリ内に一緒に格納されるため、多数のエンティティを反復処理するのが非常に高速になります。そのため、ECS はシミュレーション、群衆、または弾幕ゲームで人気のある選択肢です。また、ネイティブコードが役立つ種類の作業でもあり、毎フレームこれほど多くのエンティティを更新することは、GDScript よりも C++ の方がはるかに高速です。完全な例は、Conan examples2 リポジトリで見つけることができます:
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/examples/libraries/godot-cpp/gdextension
src フォルダには拡張機能コードが含まれており、demo はそれをロードする通常の Godot プロジェクトです。
依存関係の宣言
conanfile.py は、ConanCenter から godot-cpp と flecs を要求します:
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class GDExtensionExample(ConanFile):
package_type = "shared-library"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps"
def requirements(self):
self.requires("godot-cpp/10.0.0")
self.requires("flecs/4.1.6")
def