スクリプト

はじめに

Godot 3.0以前は、ゲームのスクリプトを作成するための唯一の選択肢はGDScriptを使用することだけでした。現在、Godotには4つの(そうです、4つも!)公式言語と、追加のスクリプト言語を動的に追加する機能があります!

これは素晴らしいことです。提供される柔軟性が大きくなるからです。ですがその反面、それぞれの言語をサポートする作業がより困難になります。

ただし、Godotの「主要な」言語はGDScriptとVisualScriptです。それらを選択する主な理由は、Godotとの統合レベルが高いからです。これにより、開発作業がよりスムーズになります。どちらも洗練されたエディタと統合されています。一方、C#とC ++は別のIDEで編集する必要があります。もしもあなたが静的に型付けされた言語の大ファンであれば、C#とC ++を使用してください。

GDScript

上記のように、GDScriptはGodotで使用されるメインの言語です。 Godotとの高度な統合により、他の言語と比較していくつかの利点があります。

  • シンプルでエレガントで、Lua、Python、Squirrelなどの他の言語のユーザーになじみがあるように設計されています。
  • 読み込みとコンパイルが非常に高速です。
  • エディタの統合は、ノード、シグナル、および編集中のシーンに関連する他の多くの項目のコード補完を使用してくれるので作業するのが楽しいです。
  • ベクトル型(ベクトル、幾何学変換など)が組み込まれており、線形代数を大量に使用する場合に効率的です。
  • 静的に型指定された言語と同じくらい効率的に複数のスレッドをサポートします - Lua、SquirrelなどのVMを避けた理由のひとつはスレッド処理に制限があるからです。
  • ガベージコレクタを使用しないため、決定論によって多少の自動化(ほとんどのオブジェクトはいずれにしても参照としてカウントされる)を犠牲にします。
  • その動的な性質により、より高いパフォーマンスが必要な場合には、エンジンを再コンパイルすることなく、C++のコード・セクション(経由GDNative)を簡単に最適化することができます。

もしあなたがどの言語を使用するかをまだ決めておらず、プログラミング、特に動的型付け言語の経験があるなら、GDScriptを選んでください!

ビジュアルスクリプト

Godotは3.0から、ビジュアルスクリプトを提供しています。これは「ブロックと接続」言語の典型的な実装ですが、Godotの動作に適合しています。

ビジュアルスクリプトは、プログラマ以外のユーザーや、ゲームデザイナーやアーティストなどの他のユーザーに、コードの一部を容易にアクセスさせたい経験豊富な開発者にとっても最適なツールです。

また、プログラマがステートマシンやカスタム・ビジュアルノード・ワークフロー(対話システムなど)を構築するためにも使用できます。

.NET / C#

マイクロソフトのC#はゲーム開発者の間でお気に入りなので、公式サポートを追加しました。C#は、大量のコードが書かれた成熟した言語であり、マイクロソフトからの寛大な寄付のおかげでサポートが追加されました。

ガベージコレクタに注意する必要がありますが、パフォーマンスと使いやすさの間には優れたトレードオフがあります。

GodotはMono .NETランタイムを使用するため、理論的には、サードパーティの.NETライブラリまたはフレームワークをGodotのスクリプトに使用できます。また、F#、Boo、ClojureCLRなどの共通言語インフラストラクチャに準拠したプログラミング言語も使用できます。 ただし、実際には、C#が公式にサポートされている唯一の.NETオプションです。

GDNative / C++

最後に、3.0リリースの最も輝かしい追加の1つ:GDNativeを使用すると、Godotを再コンパイル(または再起動)しなくてもC++でスクリプトを作成できます。

内部C API Bridgeを使用しているため、任意のC++バージョンを使用することができ、生成された共有ライブラリ用のコンパイラブランドとバージョンが混在していても完全に機能します。

この言語はパフォーマンスに最適な選択肢であり、ゲーム全体で使用する必要はありません。他の部分はGDScriptまたはVisual Scriptで作成できるためです。 とはいえ、このAPIは、主にGodotの実際のC ++ APIに似ているため、明確で使いやすいです。

GDNativeインターフェイスを通じて(C++以外の)より多くの言語を利用できますが、正式なサポートはありません。

シーンのスクリプト

このチュートリアルの残りの部分では、ボタンとラベルで構成されるGUI シーンを設定し、ボタンを押す事でラベルを更新してみます。これは、次のことを示します:

  • スクリプトを作成し、ノードにアタッチします。
  • シグナルを介して UI 要素をフックします。
  • シーン内の他のノードにアクセスできるスクリプトを作成します。

次へ進む前に、GDScriptを必ずお読みください。シンプルに設計された言語であり、リファレンスは短いため、概要を把握するのに数分しかかかりません。

シーンの設定

シーンタブから「子ノードの追加」ダイアログにアクセスし(または``Ctrl+A`` を押して )、次のノードを持つ階層を作成します:

  • Panel
    • Label
    • Button

シーン ツリーは次のようになります:

../../_images/scripting_scene_tree.png

2Dエディタを使用して、ボタンとラベルを下の画像のように配置およびサイズ変更します。インスペクタ タブからテキストを設定できます。

../../_images/label_button_example.png

最後に、シーンを sayhello.tscn などの名前で保存します。

スクリプトの追加

パネルノードを右クリックし、コンテキストメニューから「スクリプトをアタッチ」を選択します:

../../_images/add_script.png

スクリプト作成ダイアログが表示されます。このダイアログボックスを使用すると、スクリプトの言語、クラス名、およびその他の関連するオプションを設定できます。

GDScriptではファイル自身がクラスを表します。そのためクラス名のフィールドは編集できません。

スクリプトをアタッチするノードはパネルなので、[継承] フィールドには自動的に「Panel」が入力されます。スクリプトの目的は、パネルノードの機能を拡張することです。

最後に、スクリプトのパス名を入力し、「作成」を選択します:

../../_images/script_create.png

その後、スクリプトが作成され、ノードに追加されます。これは、シーンタブのノードの横にある「スクリプトを開く」アイコンと、インスペクタの下のスクリプトプロパティで表示されます:

../../_images/script_added.png

スクリプトを編集するには、上の画像で強調表示されている2つのボタンのいずれかを選択します。これにより、スクリプトエディタにデフォルトのテンプレートが含まれて表示されます:

../../_images/script_template.png

テンプレートの内容はそれほど多くはありません。 _ready() 関数は、ノードとそのすべての子がアクティブなシーンに入ると呼び出されます。注:_ready() はコンストラクタではありません。コンストラクタは _init() です。

スクリプトの役割

スクリプトは、ノードに動作を追加します。ノードの機能方法、およびノードが他のノード(子、親、兄弟など)とどのように相互作用するかを制御するために使用されます。スクリプトのローカルスコープはノードです。つまり、スクリプトはそのノードによって提供される関数を継承します。

../../_images/brainslug.jpg

シグナルの処理

シグナルは、特定の種類のアクションが発生したときに「出力」され、任意のスクリプトインスタンスの任意の関数に接続できます。シグナルは主にGUIノードで使用されますが、他のノードにもシグナルが含まれ、独自のスクリプトでカスタムシグナルを定義することもできます。

このステップでは、「pressed」シグナルをカスタム関数に接続します。最初のパートは接続の形成で、2番目のパートはカスタム関数の定義です。最初のパートでは、Godotは接続を作成する2つの方法を提供します: エディタが提供するビジュアルインタフェースを使用する方法と、コードを使用する方法です。

このチュートリアルの残りの部分ではコードを使用しますが、今後のためにエディタインターフェースがどのように機能するかについて説明します。

シーンツリーでボタンノードを選択し、「ノード」タブを選択します。次に、「シグナル」が選択されていることを確認します。

../../_images/signals.png

次に、「BaseButton」の下の「pressed()」を選択し、右下の「接続...」ボタンをクリックすると、接続作成ダイアログが開きます。

../../_images/connect_dialogue.png

ダイアログの上部には、シーン中のノードの一覧が表示されており、シグナルを発するノードの名前(今回はButton)が青色でハイライト表示されています。ここで「Panel」ノードを選択します。

ダイアログの下部には、作成されるメソッドの名前が表示されます。デフォルトでは、メソッド名には発信ノードの名前(この場合は「ボタン」)が含まれ、 _ on_ [シグナルを発するノード名] _ [シグナル名] になります。

これで、ビジュアルインターフェイスの使用方法に関するガイドは終了です。ただし、これはスクリプトのチュートリアルなので、学習のために、手動で行う方法に飛び込みましょう!

これを実現するために、おそらくGodotプログラマーが最も使用する:Node.get_node()を導入します。この関数は、パスを使用して、スクリプトを持つノードに関連する、シーン内の任意の場所のノードを見つけます。

便宜上、スクリプト内の extends Panel より下にあるすべてのものを削除します。そしてスクリプトの残りの部分を手動で入力します。

ButtonとLabelはスクリプトがアタッチされているPanelの下の兄弟(同じ階層にある子要素)であるため、 _ready() 関数の下に次のように入力するとButtonをフェッチできます:

func _ready():
    get_node("Button")
public override void _Ready()
{
    GetNode("Button");
}

次に、ボタンを押したときに呼び出される関数を書きます:

func _on_Button_pressed():
    get_node("Label").text = "HELLO!"
public void _OnButtonPressed()
{
    GetNode<Label>("Label").Text = "HELLO!";
}

Finally, connect the button's "pressed" signal to _on_Button_pressed() by using Object.connect().

func _ready():
    get_node("Button").connect("pressed", self, "_on_Button_pressed")
public override void _Ready()
{
    GetNode("Button").Connect("pressed", this, nameof(_OnButtonPressed));
}

最後のスクリプトは次のようになります:

extends Panel

func _ready():
    get_node("Button").connect("pressed", self, "_on_Button_pressed")

func _on_Button_pressed():
    get_node("Label").text = "HELLO!"
using Godot;

// IMPORTANT: the name of the class MUST match the filename exactly.
// this is case sensitive!
public class sayhello : Panel
{
    public override void _Ready()
    {
        GetNode("Button").Connect("pressed", this, nameof(_OnButtonPressed));
    }

    public void _OnButtonPressed()
    {
        GetNode<Label>("Label").Text = "HELLO!";
    }
}

シーンを実行し、ボタンを押します。次の結果が得られます:

../../_images/scripting_hello.png

あら、hello!と表示されました。最初のシーンのスクリプト作成、おめでとうございます。

注釈

このチュートリアルに関するよくある誤解は、 get_node(path) の仕組みです。 特定のノードについて、 get_node(path) はその直接の子を検索します。 上記のコードでは、これはButtonがPanelの子でなければならないことを意味します。 ButtonがLabelの子である場合、取得するコードは次のようになります:

# Not for this case,
# but just in case.
get_node("Label/Button")
// Not for this case,
// but just in case.
GetNode("Label/Button")

また、ノードは型ではなく名前で参照される点に注意してください。

注釈

接続ダイアログの右側のパネルは、接続された関数のパラメータに特定の値をバインドするためのものです。さまざまな型の値を追加および削除できます。

コードアプローチでは、デフォルトでは空の、4番目の Array パラメータを使用して、これも有効にします。詳細については、 Object.connect メソッドをお読みください。