
2026/09/29 17:40
Godot で使用するあらゆる C++ ライブラリについて
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
このテキストでは、GDExtensions(または Engine モジュール)を介して godot-cpp ライブラリを Godot と統合し、コアエンジンを再コンパイルせずに GDScript とともに高性能な C++ コードを実行する方法を説明しています。Godot 4.3 以降、godot-cpp バージョン 10.0 以上は
api_version ビルドオプションによりすべての今後の 4.x バージョンに対応し、ConanCenter でのプリビルトパッケージを提供しており、これによりプラットフォーム横断で依存関係を自動的に解決します。ライブラリはデバッグ、リリース、エディタの 3 つのターゲットへコンパイルされ、ランタイムで機能タグにマッピングされます。C++17 のサポートが必要であり、MSVC では -s compiler.cppstd=17 を追加する必要があり、Linux 版では互換性の高いシステム側の libstdc++ またはリンカーバージョンスクリプトを使用した静的リンキングが求められる場合があります。
Flecs 4.1.6 は Entity Component System として使用され、大規模シミュレーション(例:
Swarm ノードを介した 100,000 のパーティクルの更新)を効率的に管理します。この Swarm ノードは Node2D を継承し、レンダリングには MultiMesh を使用し、GDREGISTER_RUNTIME_CLASS に登録することでゲームプレイ中のみ実行されます。この構成により、複雑な C++ クラスがインスペクター上で標準の Godot ノードとして機能し、GDScript からアクセスできるようになり、ビルド時間を削減するとともに、Linux および Windows での生産環境に即したワークフローをサポートします。本文
GoDot と C++: GDExtension を活用した高機能拡張の構築ガイド
GoDot は近年最も人気のあるゲームエンジンの一つとして成長し、MIT ライセンスに基づいて無料でオープンソース化されています。その軽量さと直感的な操作性により、ダウンロードして数分以内に開発を開始できます。多くのプロジェクトは GoDot の独自スクリプト言語である GDScript を用いますが、高度な処理や既存の C/C++ ライブラリの活用には追加の仕組みが必要です。
本記事では、GoDot の概要と C++ エクステンションの仕組みを解説し、Conan と godot-cpp 10 を活用して C++ ライブラリを組み込む具体的な方法を示します。具体例として、マウスカーソルから逃げる 10 万個の粒子をシミュレートする ECS(エンティティ・コンポーネント・システム)ライブラリ
flecs の導入事例を紹介します。
動画のご紹介: 「GoDot シーン内における flecs を使った 10 万個の粒子のシミュレーション(マウスカーソルからの逃避行動)」
GoDot への簡易的入門
GoDot は、2D および 3D ゲーム向けに設計された汎用エンジンです。プロジェクト内のすべての要素は、以下の 2 つの基本概念に基づいて構築されます:
- ノード(Nodes)
- 基本的な構成要素です。
- 型(
,Sprite2D
,Camera3D
,AudioStreamPlayer
など)、インスペクターで編集可能なプロパティ、およびゲームループ中に呼び出されるコールバック関数(例:Timer
,_ready()
)が割り当てられます。_process()
- シーン(Scenes)
- ディスク上の
ファイルとして保存されたノードのツリーです。.tscn - キャラクター、メニュー、レベルなど様々な用途に使用でき、他のシーン内でインスタンス化することも可能です。
- ディスク上の
通常はノードにスクリプトをアタッチして振る舞いを定義します。GDScript は Python に似た言語で、コンパイルステップがないため変更が即時反映される点から、ゲームプレイロジックの実装に適しています。
C++ 開発者にとって GoDot が魅力的なのは以下の理由です:
- エンジン自体が C++ で記述されていること。
- 再コンパイルせずに C++ で記述された拡張機能をロードできること。
- 拡張機能由来のクラスは通常のエンジンクラスとして振る舞い、エディタ上で標準ノードと共に表示され、インスペクターでのプロパティ編集や GDScript からの利用が可能です。
C++ を用いて GoDot を拡張する
GoDot に C++ コードを追加する主要な方法は以下の 2 つです:
- エンジンモジュール
- エンジン本体にコンパイルされます。
- 内部への完全なアクセス権を有します。
- 欠点: エディタや各プラットフォーム向けのエクスポートテンプレートを含む GoDot の独自ビルドを作成し、配送する必要があります。
- GDExtension(推奨)
- 公式の未変更版 GoDot を実行時に共有ライブラリ(
,.dll
,.so
など)をロードします。.dylib - エンジンとライブラリの間の通信には安定した C インターフェースが使われます。
- 公式の未変更版 GoDot を実行時に共有ライブラリ(
現在多くの人気プラグインが GDExtension の方法で配布されています。C インターフェースは冗長なため、GoDot チームはエンジン API に非常に近いインターフェースを持つ C++ ライブラリ
を提供しています。これにより、godot-cpp
Node2D や Sprite2D などのすべてのエンジンクラスに対する C++ クラスが生成されます。
ご自身のクラスはこれらのクラスから派生した通常の C++ コードです。以下に例を示します:
#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
バージョン対応について
- godot-cpp 10.0 より以降は、GoDot 4.3 以降のすべてのバージョンを単一のリリースで対応可能です。
ビルドオプションを選択することで対象となる GoDot のバージョンが決定され、C++ クラスが生成されます。api_version- 新しい GoDot で動作する拡張機能も古いバージョンには動作しないため、サポート対象とする最も古い GoDot バージョンを選択するのが望ましいです。
ビルドターゲットと機能タグ(Feature Tags)
godot-cpp は、ライブラリをロードする GoDot のビルド設定にちなんで 3 つのターゲットのいずれかのためにコンパイルされます:
- template_debug: デフォルト設定です。
ディレクティブによりデバッグチェックが有効です。エディタやデバッグ向けエクスポートで使用されます。DEBUG_ENABLED - template_release: リリース向けのエクスポート用であり、デバッグチェックは除外されています。
- editor: エディタのみでロードされるライブラリ用です。
GoDot がどのライブラリをロードするかは、
.gdextension ファイルによって実行時に決定されます。このファイルは機能タグをライブラリパスにマップします:
[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 でビルドすることを推奨しています。しかし、これは物理エンジンや機械学習ランタイムのようなサードパーティライブラリをラップする場合に不向きです。それぞれのプラットフォームとアーキテクチャに対して独自にコンパイルを行うのは困難であり、Conan を利用するアプローチが解決策となります。
ConanCenter にある
godot-cpp レシピにより、以下のようなパラメータは Conan オプションとして機能します:
: 対象とする GoDot API バージョン(4.3〜4.7)。api_version
:target
,template_debug
,template_release
。editor
各組み合わせは一度ビルドされ、すべてのプロジェクトで再利用されるため、拡張機能内部での再コンパイルが不要になります。Conan は依存関係を持つ単なる C++ プロジェクトとなり、1,900 以上のライブラリの一つや自作パッケージを
godot-cpp の隣に追加できます。
実用的な例:10 万個の粒子のスウォーム
新しい Swarm ノードを登録する GDExtension を作成し、マウスカーソルから逃げ、ウィンドウ端で跳ね返る 10 万個の粒子をシミュレーションします。これらすべては GoDot のシーン内で描画されます。
- 技術スタック: C/C++ 向け ECS ライブラリ
を使用。flecs - 利点: 同じ型のコンポーネントはメモリ上近くに格納され、多数のエンティティに対するイテレーションが非常に高速です。ネイティブコードの恩恵を大きく受けるため、この規模では 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 layout(self): cmake_layout(self) def generate(self): tc = CMakeToolchain(self) # 出力名を godot-cpp のビルドターゲットに合わせて設定します tc.cache_variables["GODOTCPP_TARGET"] = str(self.dependencies["godot-cpp"].options.target) tc.generate() def build(self): cmake = CMake(self) cmake.configure() cmake.build()
CMakeLists.txt
CMakeLists.txt は完全に標準的な CMake プロジェクトです。拡張機能は godot-cpp と flecs を静的にリンクした共有ライブラリとなり、配送する必要があるのは単一のファイルだけです。これを demo/bin 直接に配置することで、GoDot が直ちに発見します。
cmake_minimum_required(VERSION 3.15) project(gdexample LANGUAGES CXX) find_package(godot-cpp REQUIRED CONFIG) find_package(flecs REQUIRED CONFIG) add_library(gdexample SHARED src/register_types.cpp src/swarm.cpp ) target_link_libraries(gdexample PRIVATE godot-cpp flecs::flecs_static) # 出力名とディレクトリ設定 set_target_properties(gdexample PROPERTIES OUTPUT_NAME "gdexample.${GODOTCPP_TARGET}" PREFIX "lib" LIBRARY_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/demo/bin>" RUNTIME_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/demo/bin>" )
ノードの記述
Swarm クラスは Node2D から派生し、flecs ワールドを所有します。各粒子のコンポーネントは単なる構造体です。GDCLASS マクロが GoDot のクラスシステムに必要なテンプレートを追加し、_bind_methods() でプロパティ(例:count, flee_radius)を宣言することで、インスペクターに表示され GDScript から利用可能になります。
struct Position { float x, y; }; struct Velocity { float x, y; }; class Swarm : public Node2D { GDCLASS(Swarm, Node2D) int count = 100000; double flee_radius = 150.0; flecs::world world; ... protected: static void _bind_methods() { ClassDB::bind_method(D_METHOD("set_count", "count"), &Swarm::set_count); ClassDB::bind_method(D_METHOD("get_count"), &Swarm::get_count); ADD_PROPERTY(PropertyInfo(Variant::INT, "count"), "set_count", "get_count"); // ... および flee_radius についても同様 } ... };
_ready() と _process() の簡易例:
- _ready(): 各粒子に
とPosition
コンポーネントを持つエンティティを生成し、描画用のVelocity
を設定します。MultiMesh - _process(): マウスの位置を
に手渡し、システムを実行(flecs
)して得られた位置をバッファにコピーします。world.progress()
void Swarm::_ready() { // 各粒子へのコンポーネント付与 for (int i = 0; i < count; i++) { world.entity().set<Position>({ ... }).set<Velocity>({ ... }); } // システム定義 world.system<Position, Velocity>("Move").each([this](flecs::iter &it, size_t, Position &p, Velocity &v) { // マウスから逃避し、移動し、ウィンドウ端で跳ね返る処理 }); // MultiMeshInstance2D の設定(描画用) ... } void Swarm::_process(double p_delta) { mouse = get_local_mouse_position(); world.progress(static_cast<float>(p_delta)); // 位置の更新とバッファへのコピー render_query.each([&](const Position &p, const Velocity &v) { ... }); multimesh->set_buffer(buffer); }
エクステンションの登録
最後に
register_types.cpp でクラスを登録します:
void initialize_gdexample_module(ModuleInitializationLevel p_level) { if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } GDREGISTER_RUNTIME_CLASS(Swarm); // ランタイムクラスとして登録 }
- ランタイムクラス: エディタ内でプレースホルダーとして機能し、コードはゲーム実行時のみ実行されます。
- エントリーポイント:
ファイルで指定された.gdextension
が呼ばれます。gdexample_library_init()
ビルドと実行
すべてが整った状態で拡張機能をビルドするには単一のコマンドだけです:
$ conan build . --build=missing ... [100%] Linking CXX shared library .../demo/bin/libgdexample.template_debug.dylib [100%] Built target gdexample
- Conan が
とgodot-cpp
を解決し、必要であればソースからビルドします。flecs - CMake インテグレーションを生成して最終的に拡張機能をビルドします。
注記:
は C++17 を必要とします。古い標準を使用している場合(MSVC など)、コマンドにgodot-cppを追加してください。-s compiler.cppstd=17
次に GoDot 4.7 を起動し、プロジェクトマネージャーで「Import」して
demo/project.godot を選択します。GoDot は bin/gdexample.gdextensionを読み取り、Swarm ノードをエディタ内で表示できるようになります(Node2D セクションより「新しいノードを作成」)。
デモのメインシーンを選択すると、インスペクター上で
count や flee_radius のプロパティが表示され、変更可能です。Play を押してマウスで粒子を押回すと、シミュレーションが動作します。パラメータを変更して再度 Play することで、より多くの粒子や広い逃避半径を持つスウォームを作成できます。
結論
GDExtension と godot-cpp を用いることで、C++ でエンジンクラスを記述でき、Conan がビルドの自動化を担当します。このアプローチは、拡張機能の配布においても大きな利点を持ちます(設定変更のみで各プラットフォームに対応可能)。
- Linux 用注記:デフォルトでは
を動的にリンクするため、目標システムにはそれ以上のバージョンが必要です。広範な互換性を得る場合は、ツールチェーンおよびシステムライブラリとの互換性を保ってビルドするか、静的にリンクする方法があります。libstdc++
より多くの拡張機能について学ぶためには、完全な例を試して
godot-cpp の文書を確認することをお勧めします。フィードバックや問題については Conan の GitHub リポジトリで知らせください。
楽しいゲーム開発ライフを!