imog

主にUnityとかの事を書いています

GodotEngineのsignalのメモ

最近趣味でGodotEngineを触り始めている。

Godot Engine - Free and open source 2D and 3D game engine

新しい単語や概念が多いので、とりあえず備忘録として。 とにかく日本語の資料が少ない。

signalとは

文字通り信号を送る機能。

http://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/gdscript_basics.html#signals

Godotではあらゆるイベントが発生した際にそれを通知するための仕組みがあり、それをシグナルと呼んでいる。

例えば衝突判定を扱うCollisionObject2Dは、3つのシグナルが存在している。

image

input_event mouse_entered mouse_exited は同名のメソッドをスクリプトで書いたら勝手にコールバックとして呼ばれる。 Unityで言うOnCollisionほげほげメソッドを実装する感覚に近い。

そしてこのシグナルは、自分で定義して通知することができる。

シグナルを自作する

例えば以下を考えてみる

  • Ankouノードは、任意のタイミングで「戦車前進」の通知を飛ばす
  • Kameノードは、「戦車前進」の通知が来たら何かする

image

Ankouはシグナルを通知する側なのでこんな感じで書く

extends Node

# 自作シグナル
signal panzer_vor

func _ready():
    # 自身の panzer_vor シグナルを受けとったら _on_panzer_vor にコールバック
    connect("panzer_vor", self, "_on_panzer_vor")
    # シグナルを送信する
    emit_signal("panzer_vor")
    
func _on_panzer_vor():
    print("Go Ankou")

やることは以下の三つ。

  • シグナルの定義
  • シグナルを受け取れるよう接続
  • シグナルの送信

自作シグナルは signal hoge で定義。 それを受け取れるよう connect でシグナル名、受け取るオブジェクト、コールバック先を書く。最後に emit_signal で送信する。

この時点でエディタ上で panzer_vor シグナルが見えるようになる。

image

Kameさんノードはシグナルを受け取るためにAnkouと接続する必要があるが、それ以外は何も変わらない。

extends Node

func _ready():
    var ankou_node = $Ankou
    ankou_node.connect("panzer_vor", self, "_on_panzer_vor")

func _on_panzer_vor():
   print("Go Kame")

通知を受け取るのをやめる場合、disconnect メソッドを呼ぶと終了できる。

一度Connectしたものを再度Connectしようとするとデバッガでエラーが発生するがゲームは落ちない。

基本的にノード同士のやりとりはシグナルでやったほうが楽そう。

GUI上でシグナルを受け取る

上記connect に相当する部分はGUI上でも定義できる。

image

ここをダブルクリックするとウィンドウが出てくる

image

ノードを指定してコールバックメソッド名を書く。Make FunctionオプションをONにしたらメソッドを生成までやってくれる。

image

適切に設定完了すると、GUI上でコールバック先まで確認できるようになる。

動的に設定しないのであれば、ここで書いてしまった方がわかりやすいかもしれない。

Godotユーザ増えてほしい