Godot Engine超基本メモ「ノードとシグナル」

Godot Engineを触って、色々試したりしてるんですが、超基本的な事を備忘録として残していきます。

ノード

Godot Engineはどんなものもノードとしてシーンに追加していく。
ノードはプログラム的に言うとすべてクラスで、シーンに追加するということはインスタンス化してる。

ノードの子としてノードを追加していく事でツリーを作る。

image-20200329013039828

継承の概念がわかっていないと、ノードは少しわかりづらいかもしれない。
どんなエンジンもそうだけど、継承することで拡張できている機能というのは大量にある。

ノードの種類

ざっくり分けると以下。

  • 3D (Spatial)
  • Canvas Item
    • Node2D
    • Control
  • Resource
  • Helper Class

細かくはいろいろあるけど、とりあえずはざっくり。

Spatial (3D)

3D空間に置くものすべての親。
3Dの座標とかそういう必要な情報が詰まってるやつ。

Canvas Item

2D表示するすべての親。
GUIもそうだし、キャラクターだってCanvas Itemなのさ。

Node2D

2D空間として配置するカメラとかキャラクターとかの親。
GUI以外って感じで使う(GUIで使うことももちろん出来る)

Control

GUI関連の便利機能の親。
例えばレスポンシブレイアウトの機能や、ボタンなどのコンポーネントも。
ちょっとレイアウト関連のルールが難しいけど、慣れるとどんな比率の画面にも対応できるすげーGUIが作れる。

Resource

2D空間にも3D空間にも配置されないもの。
例えばマテリアルとかテクスチャとかスプライトとか。

シーンにはインスタンスしか置けない故に、上記までのノード(SpatialやNode2D)を継承しているクラスだけがシーンに干渉できるわけだ。

ではResourceはというと、それらのノードが参照するための、まさにリソース(資産)ということ。
スクリプトやシーンもオブジェクトなので、Resourceに近い存在。

Helper Class

公式ドキュメントではヘルパークラスという名前で出てくるけど、要するにその他。
とはいえそれぞれがすごく便利な機能を持っていて、各ノードの手助けをしてくれるすごいクラスたち。

例えばTimerは、空間には置けないが、子ノードとしてツリーに含めることができる。
そして、Timerを起動すれば、好きな間隔でシグナルを発行してくれるのだ。

ノード同士の参照

ノードの参照は簡単だ。
エクスプローラーなどと同じように、相対パス・絶対パスでアクセスする事が出来る。

var root_node := get_node("/")
var parent_node := get_node("../")
var child_node := get_node("./Child")
var child_node_s := $Child

上記のような書き方ができる。
これで、指定したノードにアクセスできるので、パラメーターを変えたりなんなりできる。

ざっくりまとめ

空間に置くノードは、Resourceやヘルパークラスを装備して配置することで、かなり強力なインスタンスとしてシーンで活躍できるイメージ。

ActionScriptをやってた身としてはadd_childの概念そのもので、要するにムービークリップの入れ子みたいな感覚だ。

シグナル

シグナルは強力。

要するにイベントリスナーなんだけど、独自にシグナルを発行する事も出来る。
つまり、何かの変数を毎フレーム監視するような仕組みを作る必要がない。

image-20200329022321443

例えばTweenノードなら、トゥイーンが始まった瞬間や終わった瞬間、トゥイーンしている間だけが取得できれば十分拡張可能だろう。

image-20200329022513960

必要なシグナルを選択して、ノードウィンドウの下にある「接続」ボタンを押すと、接続先が選択できる。
接続先はスクリプトになるので、スクリプトがアタッチされているノードを選ぶだけだ。

そして、そのスクリプト内のどの関数と接続するかを設定できるため、かなり簡単にイベント発行から受け取って処理する流れが作れる。

独自シグナルをスクリプト内で発行する

# シグナルを定義
signal test_signal

# 初期化処理
func _ready():
    # シグナルを登録(シグナル名、接続先、接続先の関数名)
    connect("test_signal", self, "_on_test_signal")
    # シグナルを発行
    emit_signal("test_signal")

# シグナルを受け取った後の処理
func _on_test_signal():
    print("test")

接続先は自分(self)である必要はない。
接続先に指定した関数があれば実行される。

ざっくりまとめ

冒頭で言った通り、毎フレーム行う処理が劇的に減る。
これだけでもシグナルは十分便利。

お腹すいたので今日はこの辺で。

Related Posts

Godot Engineの学習メモ「タイル衝突の検出」
Godot Engineにお熱のSaitosです。 惚れるでコレェ!って機能や発見をメモしていこうと思います。 タイル検出 実はタイル(の編集)機能はそこま...
Gamemaker Studio2からGodot Engineにエンジン移行しました
あれだけ好きだったGamemaker Studio2ですが、今回思い切ってGodot Engineに乗り換えました。 いろんな理由があるのですが、...