GDNative C++の例

はじめに

このチュートリアルは、GDNative C exampleで示されている情報の上に基づいているので、最初にそれを読むことを強くお勧めします。

GDNativeのC ++バインディングはNativeScript GDNative APIの上に構築されており、C ++を使用してGodotでノードを「拡張」するためのより良い方法を提供します。これは、GDScriptでスクリプトを記述するのと同じですが、代わりにC ++で記述します。

Godot 3.1では、GDNativeチームによって、より優れたC ++バインディングライブラリを構築できるようにするNativeScript 1.1の追加機能が導入されました。これらの変更は現在masterブランチにマージされており、今後の方法になります。 Godot 3.0もサポートするC ++ GDNativeプラグインを作成する場合は、3.0ブランチとNativeScript 1.0構文を使用する必要があります。この記事ではそれらを並べて示します。

このチュートリアルで作成する完全な例を GitHub <https://github.com/BastiaanOlij/gdnative_cpp_example> からダウンロードできます。

プロジェクトの設定

必要な前提条件がいくつかあります:

  • Godot 3.x実行可能ファイル、
  • C ++コンパイラ、
  • ビルドツールとしてのSCons、
  • godot-cppリポジトリ<https://github.com/GodotNativeTools/godot-cpp> _のコピー。

コンパイルも参照してください。ビルドツールは、ソースからGodotをコンパイルするために必要なツールと同じです。

これらのリポジトリをGitHubからダウンロードすることも、Gitに作業を任せることができます。これらのリポジトリには、Godotのバージョンごとに異なるブランチがあることに注意してください。 Godotの以前のバージョン用に書かれたGDNativeモジュールは、(3.0と3.1の間のARVRインターフェースの1つの重大な変更を除いて)新しいバージョンでも機能します。また、 api.json の生成に使用するGodotのバージョンが最小のバージョンになることに注意してください。

Git を使用してプロジェクトをバージョン管理する場合は、Git サブモジュールとして追加することをお勧めします:

mkdir gdnative_cpp_example
cd gdnative_cpp_example
git init
git submodule add https://github.com/GodotNativeTools/godot-cpp
cd godot-cpp
git submodule update --init
mkdir gdnative_cpp_example
cd gdnative_cpp_example
git init
git submodule add -b 3.0 https://github.com/GodotNativeTools/godot-cpp
cd godot-cpp
git submodule update --init

リポジトリを単にダウンロードするか、プロジェクトフォルダに複製する場合は、フォルダのレイアウトをここで説明したものと同じにしてください。ここで紹介するコードの多くは、プロジェクトがこのレイアウトに従うことを前提としています。

両方のリポジトリをプルするために、必ず再帰的にクローンを作成してください:

mkdir gdnative_cpp_example
cd gdnative_cpp_example
git clone --recursive https://github.com/GodotNativeTools/godot-cpp
mkdir gdnative_cpp_example
cd gdnative_cpp_example
git clone --recursive -b 3.0 https://github.com/GodotNativeTools/godot-cpp

注釈

godot-cpp にはネストされたサブモジュールとして godot_headers が含まれるようになりました。手動でダウンロードした場合は、 godot-cpp フォルダー内に godot_headers を配置してください。

この方法で行う必要はありませんが、管理するのが最も簡単であることがわかりました。リポジトリをダウンロードするだけの場合、またはリポジトリをフォルダに複製するだけの場合は、ここで紹介するコードの多くがプロジェクトにこのレイアウトを持つことを前提としているので、フォルダレイアウトは、ここで設定したのと同じものにしておいてください。

概要で指定したリンクからサンプルを複製した場合、サブモジュールは自動的に初期化されません。次のコマンドを実行する必要があります。

cd gdnative_cpp_example
git submodule update --init --recursive

これにより、これら2つのリポジトリがプロジェクトフォルダに複製されます。

C++バインディングのビルド

前提条件に書かれた物をダウンロードしたので、C ++バインディングを作成します。

リポジトリには、現在のGodotリリースのメタデータのコピーが含まれていますが、新しいバージョンのGodot用にこれらのバインディングをビルドする必要がある場合は、単にGodot実行可能ファイルを呼び出すだけです。

godot --gdnative-generate-json-api api.json

結果の api.json ファイルをプロジェクトフォルダに配置し、 use_custom_api_file = yes custom_api_file = .. / api.json を以下のsconsコマンドに追加します。

To generate and compile the bindings, use this command (replacing <platform> with windows, linux or osx depending on your OS):

cd godot-cpp
scons platform=<platform> generate_bindings=yes
cd ..

この手順にはしばらく時間がかかります。完了後、プロジェクト内の godot-cpp/bin/ に、コンパイルされた静的ライブラリが格納されているはずです。

将来のある時点で、コンパイル済みのバイナリが利用可能になり、この手順は省略可能になります。

注釈

Windows または Linux のコマンドに bits=64 を追加する必要がある場合があります。我々は自動検出の改善に引き続き取り組んでいます。

シンプルなプラグインの作成

次に、実際のプラグインを作成します。まず、空のGodotプロジェクトを作成し、そこにいくつかのファイルを配置します。

Godotを開き、新しいプロジェクトを作成します。この例では、GDNativeモジュールのフォルダ構造内に demo という名前のフォルダを配置します。

デモプロジェクトでは、"Main" というノードを含むシーンを作成し、main.tscn として保存します。それについては後で説明します。

最上位の GDNativeモジュールフォルダに戻り、ソース ファイルを配置する src というサブフォルダも作成します。

これで、GDNativeモジュールに demogodot-cppgodot_headersおよび src ディレクトリが含まれるはずです。

作成するGDNativeノードのヘッダーファイルを、`` src``フォルダ内に作成することから始めます。gdexample.h という名前を付けます:

#ifndef GDEXAMPLE_H
#define GDEXAMPLE_H

#include <Godot.hpp>
#include <Sprite.hpp>

namespace godot {

class GDExample : public Sprite {
    GODOT_CLASS(GDExample, Sprite)

private:
    float time_passed;

public:
    static void _register_methods();

    GDExample();
    ~GDExample();

    void _init(); // our initializer called by Godot

    void _process(float delta);
};

}

#endif
#ifndef GDEXAMPLE_H
#define GDEXAMPLE_H

#include <Godot.hpp>
#include <Sprite.hpp>

namespace godot {

class GDExample : public godot::GodotScript<Sprite> {
    GODOT_CLASS(GDExample)

private:
    float time_passed;

public:
    static void _register_methods();

    GDExample();
    ~GDExample();

    void _process(float delta);
};

}

#endif

上記にはいくつかの注意事項があります。まず、すべての基本的な定義を含む Godot.hpp を含めています。その後、Spriteクラスへのバインディングを含む ``Sprite.hpp``を含めます。このクラスが作成するモジュールで拡張されます。

GDNativeのすべてがこの名前空間内で定義されているため、namespace godot を使用しています。

次に、コンテナ クラスを通じてSpriteから継承するクラス定義を作成します。これについては、後でいくつかの副作用が表示されます。GODOT_CLASS マクロはいくつかの内部的なものをセットアップします。

その後、time_passed という単一のメンバー変数を宣言します。

メソッドを定義する次のブロックでは、明示的にコンストラクタとデストラクタが定義されています。その他の関数のうち2つのは見慣れたものですが、新しいメソッドが1つあります。

最初は _register_methods で、これはGodotがNativeScriptで呼び出すことができるメソッドと、それが公開するプロパティを調べるために呼び出す静的関数です。2つ目は _process 関数で、GDScriptで慣れている _process 関数とまったく同じように機能します。3つ目は、Godotがオブジェクトを適切に設定した後に呼び出される _init 関数です。コードを配置しなくても存在する必要があります。

gdexample.cpp ファイルを作成して関数を実装してみましょう:

#include "gdexample.h"

using namespace godot;

void GDExample::_register_methods() {
    register_method("_process", &GDExample::_process);
}

GDExample::GDExample() {
}

GDExample::~GDExample() {
    // add your cleanup here
}

void GDExample::_init() {
    // initialize any variables here
    time_passed = 0.0;
}

void GDExample::_process(float delta) {
    time_passed += delta;

    Vector2 new_position = Vector2(10.0 + (10.0 * sin(time_passed * 2.0)), 10.0 + (10.0 * cos(time_passed * 1.5)));

    set_position(new_position);
}
#include "gdexample.h"

using namespace godot;

void GDExample::_register_methods() {
    register_method((char *)"_process", &GDExample::_process);
}

GDExample::GDExample() {
    // Initialize any variables here
    time_passed = 0.0;
}

GDExample::~GDExample() {
    // Add your cleanup procedure here
}

void GDExample::_process(float delta) {
    time_passed += delta;

    Vector2 new_position = Vector2(10.0 + (10.0 * sin(time_passed * 2.0)), 10.0 + (10.0 * cos(time_passed * 1.5)));

    owner->set_position(new_position);
}

これは簡単なはずです。ヘッダーファイルで定義したクラスの各メソッドを実装しています。register_method の呼び出しでは必ず _ process メソッドを公開する必要があることに注意してください。さもないと、Godotはそれを使用できなくなります。ただし、コンストラクタ、デストラクタ、および_init 関数についてGodotに伝える必要はありません。

もう1つの注目すべきメソッドは、_ process 関数です。これは、経過時間を追跡し、単純にサイン関数とコサイン関数を使用して、スプライトの新しい位置を計算するだけです。注目すべき点は、owner->set_position を呼び出して、Spriteのメソッドのビルドの1つを呼び出すことです(NativeScript 1.0の場合)。これは、クラスがコンテナクラスであるためです。owner は、スクリプトが関連する実際のSpriteノードを指します。今後のNativeScript 1.1では、クラスで直接 set_position を呼び出すことができます。

必要なC++ファイルがもう1つあるので、それには gdlibrary.cpp``という名前を付けます。 GDNativeプラグインには複数のNativeScriptを含めることができ、上記の ``GDExample を実装したように、それぞれに独自のヘッダーとソースファイルがあります。今必要なのは、GDNativeプラグイン内のすべてのNativeScriptについてGodotに伝える小さなコードです。

#include "gdexample.h"

extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
    godot::Godot::gdnative_init(o);
}

extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
    godot::Godot::gdnative_terminate(o);
}

extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
    godot::Godot::nativescript_init(handle);

    godot::register_class<godot::GDExample>();
}

ここで実装されている3つの関数は名前空間なしで定義する必要があるため、ここでは godot という名前空間を使用していないことに注意してください。

godot_gdnative_init および godot_gdnative_terminate 関数は、Godotがプラグインをロードするときとアンロードするときにそれぞれ呼び出されます。ここで行っているのは、バインディングモジュールの関数を解析してそれらを初期化することだけですが、必要に応じてより多くのことを設定する必要がある場合があります。

重要な関数は godot_nativescript_init``と呼ばれる3番目の関数です。まず、通常の処理を行うバインディングライブラリの関数を呼び出します。その後、ライブラリの各クラスに対して関数 ``register_class を呼び出します。

プラグインのコンパイル

SConsがビルドに使用する SConstruct ファイルを手で簡単に書くことはできません。この例では、準備されている his hardcoded SConstruct file を使用します。以降のチュートリアルでは、これらのビルドファイルの使用方法について、よりカスタマイズ可能で詳細な例を取り上げます。

注釈

この SConstruct``ファイルは、最新の ``godot-cpp マスターで使用するために作成されました。古いバージョンで使用するときは必要に応じて小さな変更を加えるか、Godot 3.0 のドキュメント内の SConstruct ファイルを参照する必要があります。

SConstruct ファイルをダウンロードしたら、godot-cppgodot_headersdemo 以外のGDNativeモジュールフォルダに配置し、次を実行します:

scons platform=<platform>

これで ``demo/bin/<platform> `` 内でモジュールを見つけることができるはずです。

注釈

ここでは、godot-cpp と gdexample ライブラリの両方を、デバッグビルドとしてコンパイルしました。最適化されたビルドの場合は、target=release スイッチを使用してコンパイルする必要があります。

GDNativeモジュールの使用

Godotに戻る前に、demo/bin/ にさらに2つのファイルを作成する必要があります。どちらもGodotエディタを使用して作成できますが、直接作成する方が高速な場合があります。

1つ目は、プラットフォーム別に読み込む必要があるダイナミック ライブラリをGodotに知らせるファイルで、gdexample.gdnlib と呼ばれます。

[general]

singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=false

[entry]

X11.64="res://bin/x11/libgdexample.so"
Windows.64="res://bin/win64/libgdexample.dll"
OSX.64="res://bin/osx/libgdexample.dylib"

[dependencies]

X11.64=[]
Windows.64=[]
OSX.64=[]

このファイルには、モジュールの読み込み方法を制御する general セクションが含まれています。また、今のところ godot_ に残すべきプレフィックスセクションも含まれています。これを変更する場合は、エントリポイントとして使用されるさまざまな関数の名前を変更する必要があります。これは、動的ライブラリをデプロイできないiPhoneプラットフォーム用に追加されましたが、GDNativeモジュールは静的にリンクされています。

entry セクションは重要な要素です: サポートされている各プラットフォームのプロジェクトのファイルシステム内の動的ライブラリの場所をGodotに指示します。また、プロジェクトをエクスポートするときにそのファイルだけがエクスポートされるため、データパックにはターゲットプラットフォームと互換性のないライブラリは含まれません。

最後に、``dependencies``(依存関係)セクションでは、組み込みを許可する必要がある追加の動的ライブラリの名前を記載します。これは、GDNativeプラグインが他のユーザーのライブラリを実装し、サードパーティの動的ライブラリをプロジェクトに提供する必要がある場合に重要です。

Godot内の gdexample.gdnlib ファイルをダブルクリックすると、さらに多くのオプションを設定できます:

../../../_images/gdnative_library.png

作成する必要がある2番目のファイルは、プラグインに追加した各NativeScriptで使用されるファイルです。gdexampleのNativeScriptに ``gdexample.gdns``という名前を付けます。

[gd_resource type="NativeScript" load_steps=2 format=2]

[ext_resource path="res://bin/gdexample.gdnlib" type="GDNativeLibrary" id=1]

[resource]

resource_name = "gdexample"
class_name = "GDExample"
library = ExtResource( 1 )

これは標準のGodotリソースです。シーンで直接作成することもできますが、ファイルに保存すると、他の場所で再利用するのがはるかに簡単になります。このリソースはgdnlibファイルを指しているため、どの動的ライブラリにNativeScriptが含まれているかを Godot が知ることができます。また、プラグイン内の使用したいNativeScriptを識別する class_name も定義します。

Godotに戻る時間です。最初に作成したメインシーンを読み込み、シーンにスプライトを追加します:

../../../_images/gdnative_cpp_nodes.png

このスプライトに Godot ロゴをテクスチャとして割り当て、Centered プロパティを無効にし、gdexample.gdns ファイルをスプライトの Script プロパティにドラッグします。

../../../_images/gdnative_cpp_sprite.png

プロジェクトを実行する準備ができました:

../../../_images/gdnative_cpp_animated.gif

プロパティの追加

GDScriptでは、export キーワードを使用してスクリプトにプロパティを追加できます。GDNativeでは、プロパティを登録する必要があり、これを行う2つの方法があります。メンバーに直接バインドすることも、セッター関数とゲッター関数を使用することもできます。

注釈

第3のオプションもあります。GDScriptと同様に、オブジェクトの _get_property_list_get および _set メソッドを直接実装できますが、このチュートリアルの範囲をはるかに超えています。

直接バインドする方法から始めて両方を調べます。波の振幅を制御できるプロパティを追加しましょう。

gdexample.h ファイルでは、次のようなメンバー変数を追加するだけです:

...
private:
    float time_passed;
    float amplitude;
...

gdexample.cpp ファイルでは、いくつかの変更を行う必要があります。変更するメソッドのみを表示しているので、省略されている行は削除しないでください:

void GDExample::_register_methods() {
    register_method("_process", &GDExample::_process);
    register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
}

void GDExample::_init() {
    // initialize any variables here
    time_passed = 0.0;
    amplitude = 10.0;
}

void GDExample::_process(float delta) {
    time_passed += delta;

    Vector2 new_position = Vector2(
        amplitude + (amplitude * sin(time_passed * 2.0)),
        amplitude + (amplitude * cos(time_passed * 1.5))
    );

    set_position(new_position);
}
void GDExample::_register_methods() {
    register_method((char *)"_process", &GDExample::_process);
    register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
}

GDExample::GDExample() {
    // initialize any variables here
    time_passed = 0.0;
    amplitude = 10.0;
}

void GDExample::_process(float delta) {
    time_passed += delta;

    Vector2 new_position = Vector2(
        amplitude + (amplitude * sin(time_passed * 2.0)),
        amplitude + (amplitude * cos(time_passed * 1.5))
    );

    owner->set_position(new_position);
}

これらの変更を加えてモジュールをコンパイルすると、インターフェイスにプロパティが追加されていることがわかります。これでこのプロパティを変更できるようになったため、プロジェクトを実行すると、Godotアイコンが大きな図に沿って移動することがわかります。

注釈

Godotエディタが新しく追加されたプロパティを自動的に取得するには、gdexample.gdnlib ファイルの reloadable プロパティを rue に設定する必要があります。

ただし、この設定は、ツールクラスを使用する場合は特に注意して使用する必要があります。エディタは、GDNativeライブラリによって管理されるスクリプトインスタンスがアタッチされたオブジェクトを保持する可能性があるためです。

同じようなことを、アニメーションの速度のために、セッターとゲッター関数を使用しておこないます。gdexample.h ヘッダーファイルには、さらに数行のコード追加しか必要ありません:

...
    float amplitude;
    float speed;
...
    void _process(float delta);
    void set_speed(float p_speed);
    float get_speed();
...

このために gdexample.cpp ファイルにさらにいくつかの変更を行う必要がありますが、ここでも変更されたメソッドのみを表示しているため、省略されているものを削除しないでください:

void GDExample::_register_methods() {
    register_method("_process", &GDExample::_process);
    register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
    register_property<GDExample, float>("speed", &GDExample::set_speed, &GDExample::get_speed, 1.0);
}

void GDExample::_init() {
    // initialize any variables here
    time_passed = 0.0;
    amplitude = 10.0;
    speed = 1.0;
}

void GDExample::_process(float delta) {
    time_passed += speed * delta;

    Vector2 new_position = Vector2(
        amplitude + (amplitude * sin(time_passed * 2.0)),
        amplitude + (amplitude * cos(time_passed * 1.5))
    );

    set_position(new_position);
}

void GDExample::set_speed(float p_speed) {
    speed = p_speed;
}

float GDExample::get_speed() {
    return speed;
}
void GDExample::_register_methods() {
    register_method((char *)"_process", &GDExample::_process);
    register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
    register_property<GDExample, float>("speed", &GDExample::set_speed, &GDExample::get_speed, 1.0);
}

GDExample::GDExample() {
    // initialize any variables here
    time_passed = 0.0;
    amplitude = 10.0;
    speed = 1.0;
}

void GDExample::_process(float delta) {
    time_passed += speed * delta;

    Vector2 new_position = Vector2(
        amplitude + (amplitude * sin(time_passed * 2.0)),
        amplitude + (amplitude * cos(time_passed * 1.5))
    );

    owner->set_position(new_position);
}

void GDExample::set_speed(float p_speed) {
    speed = p_speed;
}

float GDExample::get_speed() {
    return speed;
}

プロジェクトがコンパイルされると、speedという別のプロパティが表示されます。値を変更すると、アニメーションが速くなったり遅くなったりします。

この例では、セッターとゲッターを使用する明らかな利点はありません。書いただけのコードです。簡単な例をあげると、変数の変更と同時に何らかの反応を行いたい場合などにはセッターの正当な理由があるかもしれません。ですが多くの場合、変数をバインドするだけで十分です。

ゲッターとセッターは、オブジェクトの状態に基づいて追加の選択を行う必要がある、より複雑なシナリオではるかに役立ちます。

注釈

わかりやすくするために、register_property <class, type>メソッド呼び出しのオプションパラメータは省略しました。これらのパラメータは rpc_modeusagehint および hint_string です。これらを使用して、Godot側でのプロパティの表示方法と設定方法をさらに構成できます。

最新のC++コンパイラでは、クラスと変数の型を推測するので、register_property メソッドの <GDExample, float> 部分を省略できます。ただし、これについてはさまざまな経験があります。

シグナル

最後に、シグナルはGDNativeでも完全に機能します。モジュールが別のオブジェクトによって与えられたシグナルに反応するには、そのオブジェクトに対して connect を呼び出す必要があります。揺れるゴドーのアイコンのための良い例を考えることができませんので、もっと完全な例を紹介する必要があります。

まず、これは必須の構文です:

some_other_node->connect("the_signal", this, "my_method");
some_other_node->connect("the_signal", owner, "my_method");

_register_methods メソッドで事前に登録した場合にのみ my_method を呼び出すことができることに注意してください。

オブジェクトがシグナルを送信する方がはるかに一般的です。揺れるゴドーのアイコンのために、それがどのように機能するかを示す目的であまり意味の無いことをします。1秒が経過するたびにシグナルを発信し、新しい位置を伝達します。

gdexample.h ヘッダーファイルでは、新しいメンバー time_emit を定義するだけです:

...
    float time_passed;
    float time_emit;
    float amplitude;
...

`` gdexample.cpp``の変更は今回はもう少し複雑です。まず、_ init メソッドまたはコンストラクタで time_emit = 0.0; を設定する必要があります。ですが、他の2つは、必要な変更を1つずつ見ていきます。

_register_methods メソッドでシグナルを宣言する必要があり、これを次のように行います:

void GDExample::_register_methods() {
    register_method("_process", &GDExample::_process);
    register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
    register_property<GDExample, float>("speed", &GDExample::set_speed, &GDExample::get_speed, 1.0);

    register_signal<GDExample>((char *)"position_changed", "node", GODOT_VARIANT_TYPE_OBJECT, "new_pos", GODOT_VARIANT_TYPE_VECTOR2);
}
void GDExample::_register_methods() {
    register_method((char *)"_process", &GDExample::_process);
    register_property<GDExample, float>("amplitude", &GDExample::amplitude, 10.0);
    register_property<GDExample, float>("speed", &GDExample::set_speed, &GDExample::get_speed, 1.0);

    Dictionary args;
    args[Variant("node")] = Variant(Variant::OBJECT);
    args[Variant("new_pos")] = Variant(Variant::VECTOR2);
    register_signal<GDExample>((char *)"position_changed", args);
}

ここでは、最新バージョンのgodot-cppで素晴らしい改善が見られます。register_signal メソッドは、最初にシグナル名を受け取り、次にパラメータ名と各パラメータのタイプを指定する値のペアを指定する、単一の呼び出しだけでシグナルを送信します。

NativeScript 1.0の場合、まずシグナルに渡す引数のタイプをGodotに伝える辞書を作成し、それを登録します。

次に _process メソッドを変更する必要があります:

void GDExample::_process(float delta) {
    time_passed += speed * delta;

    Vector2 new_position = Vector2(
        amplitude + (amplitude * sin(time_passed * 2.0)),
        amplitude + (amplitude * cos(time_passed * 1.5))
    );

    set_position(new_position);

    time_emit += delta;
    if (time_emit > 1.0) {
        emit_signal("position_changed", this, new_position);

        time_emit = 0.0;
    }
}
void GDExample::_process(float delta) {
    time_passed += speed * delta;

    Vector2 new_position = Vector2(
        amplitude + (amplitude * sin(time_passed * 2.0)),
        amplitude + (amplitude * cos(time_passed * 1.5))
    );

    owner->set_position(new_position);

    time_emit += delta;
    if (time_emit > 1.0) {
        Array args;
        args.push_back(Variant(owner));
        args.push_back(Variant(new_position));
        owner->emit_signal("position_changed", args);

        time_emit = 0.0;
    }
}

1秒が経過した後、シグナルを発信し、カウンターをリセットします。godot-cppの新しいバージョンでは、パラメータ値を emit_signal に直接追加できます。 NativeScript 1.0では、最初に値の配列を作成してから emit_signal を呼び出します。

コンパイルしたら、Godotに移動してスプライトノードを選択できます。``ノード`` タブで新しいシグナルを見つけ、接続を押してリンクします。メインノードにスクリプトを追加し、次のように信号を実装しました:

extends Node

func _on_Sprite_position_changed(node, new_pos):
    print("The position of " + node.name + " is now " + str(new_pos))

毎秒、単に自分の位置をコンソールに出力します。

NativeScript1.1 対 NativeScript1.0

これまでの例では、古い構文と新しい構文に大きな違いはないようです。クラスの定義が若干異なり、owner メンバーを使用してオブジェクトのGodot側のメソッドを呼び出す必要がなくなりました。多くの改善点は内部に隠されています。

この例では、単純な変数と単純なメソッドのみを扱います。特に、他のオブジェクトへの参照の受け渡しを開始するか、より複雑なパラメータを必要とするメソッドを呼び出し始めたりすると、NativeScript 1.1はその利点を発揮し始めます。

次のステップ

上記は簡単な例にすぎませんが、基本を示してくれることを願っています。この例を基にして、C++を使用してGodotのノードを制御する本格的なスクリプトを作成できます。

Godotエディタが開いたままでプラグインを編集および再コンパイルできるはずです。ライブラリの構築が完了したら、プロジェクトを再実行してください。