Godot4 メンバ変数の変更時にカスタムシグナルを発するスクリプト例

無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、作成したクラスのメンバ変数の値の設定を行う際に呼び出される setter 関数を利用して、メンバ変数の値が変更された際に接続済み関数を呼び出す独自のカスタムシグナルを実装したスクリプト例テストシーンの作成、その実行結果を紹介します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。

前回の記事

前回は、メンバ変数の設定・取得の際に呼び出される setter, getter 用の関数を実装して、値を変更・取得する際に、それらの関数が呼び出されることを確認しました。

テストシーンへの UI の追加

前回作成したシーンのルートノードに、以下のように Button と Label 3 個を子ノードとして追加で配置します。

  • StudySetterGetterSignal (Control)
    • ButtonRandom (Button) : 1 ~ 9 のランダムな整数を int_value に加算するボタン。
    • LabelIntValue (Label) : getter, setter のついたメンバ変数 int_value の値を表示。
    • LabelCount (Label) : RandomButton が押された回数を表示。
    • LabelRandomValue (Label) : ボタンが押された際に加算した値を表示。
Godot4 StudyGetterSetterSignal のシーン作成

作成したボタンが押された際に呼び出される関数を作成します。

シーンドックの ButtonRandom ノード選択した後、ノードドック(初期配置ではインスペクタードックの右側のタブ)のシグナルタブの button_up シグナルダブルクリックして「メソッドにシグナルを接続」ダイアログを表示します。

そのダイアログで、スクリプトがすでに割り当てられているルートノード選択されていることと、作成される受信側メソッドの名前確認して「接続」ボタンを押します。
※ button_up シグナルの受信側メソッドは、_on_button_random_button_up という名前ですが、ほかの名前に変更している場合は、以下のスクリプト内のその関数の名前を変更してください。

Godot4 StudyGetterSetterSignal のシーン作成4

以上で UI の追加と、ボタンが押された際のイベントを処理する受信側メソッド作成されました。
Ctrl + Sシーン上書き保存しましょう。

getter, setter, signal を用いたスクリプト例

作成した GD スクリプトを以下の内容で上書きします。
※詳細はスクリプト内のコメントを参照してください。

extends Node
class_name StudySetterGetterSignal

## [member int_value] が変更された際に発せられるシグナルです。
## [param int_value] は設定された新しい値です。
signal int_value_changed(int_value: int)

## setter, getter のテストを行うためのメンバ変数です。
## set, get で setter, getter の関数を割り当てることで
## この変数の値を取得する際は getter, 設定する際は setter の関数が呼び出されます。
var int_value: int = 0: set = set_int_value, get = get_int_value
## [param int_value] の setter 関数です。
func set_int_value(value: int) -> void:
	print("set_int_value called. value = " + str(value))
	# 値が以前と同じ場合は何もしません。
	# getter に割り当てた関数が呼ばれ、その戻り値と value を比較します。
	if int_value == value:
		return
	int_value = value	# 値を設定
	int_value_changed.emit(value)	# シグナルを発します。
	return
## [param int_value] の getter 関数です。
func get_int_value() -> int:
	print("get_int_value called. int_value = " + str(int_value))
	return int_value

## $ButtonRandom を押した回数です。
var button_random_count: int = 0

# Called when the node enters the scene tree for the first time.
## シーンに、このスクリプトを割り当てたノードが。配置された直後に呼び出されるイベント関数です。
func _ready():
	# ラベルの表示を更新します。
	update_labels()
	# [signal StudySetterGetterSignal.int_value_changed] をメンバ関数と接続します。
	# シグナルは、エディタのノードドックから接続することもできます。
	int_value_changed.connect(Callable(self, "_on_int_value_changed"))
	return

## [signal StudySetterGetterSignal.int_value_changed] シグナルに接続した関数です。
## シグナルが発せられると呼び出されます。
func _on_int_value_changed(_int_value: int) -> void:
	# ラベルの表示を更新します。
	update_labels()
	return

## $LabelIntValue のテキストを更新します。
func update_labels() -> void:
	# int_value の値を表示するラベルのテキストを更新します。
	# このタイミングで getter 関数が呼び出されます。
	$LabelIntValue.text = "int_value = %s" % [str(int_value)]
	# button_random_count の値を表示するラベルのテキストを更新します。
	$LabelCount.text = "( %s 回目)" % [str(button_random_count)]
	return

## $ButtonRandom の [Signal BaseButton.button_up] が発せられた際に呼び出される受信側メソッドです。
func _on_button_random_button_up():
	# ボタンを押した回数を 1 増やします。
	# 先に int_value の値を変えてしまうと、 update_labels が
	# button_random_count を加算する処理よりも早く呼ばれてしまい
	# 回数が1回遅く表示されます。 (0, 0, 1, 2,...)
	button_random_count += 1
	# 1 ~ 9 の値を加算します。
	# このタイミングで setter 関数が呼び出されます。
	# また、 setter 関数の内部で [signal StudySetterGetterSignal.int_value_changed] が発せられます。
	var random_value: int = randi_range(1, 9)
	int_value += random_value
	# 直前に加算された値を更新します。
	$LabelRandomValue.text = "+ %s" % [str(random_value)]
	return

6 行目で定義したカスタムシグナルを、20 行目でメンバ変数の値が変更された直後、そのシグナルを発して接続済みの関数呼び出します。

_ready イベント関数内の 37 行目で、カスタムシグナルとメンバ関数接続しています。

カスタムシグナルと関数の接続

カスタムシグナル int_value_changed は、 _ready イベント関数内で、メンバ変数に connect 関数で接続しています。
これにより、カスタムシグナルが発せられるタイミング(例ではメンバ変数の値の変更時)で、その接続した関数が呼び出されます。

サンプルでは connect 関数を呼び出してスクリプトで接続していますが、このスクリプトを割り当てたノードシーンドックで選択してから、ノードドックを開くと、既存のシグナルと同様にカスタムシグナルもノードドックから接続できます。

Godot4 StudyGetterSetterSignal のカスタムシグナルはノードドックからも利用できます。

代入したらシグナルが呼び出されることを意識することが重要

メンバ変数に setter 関数を設定することで、 a = 0 のように単純に値を設定するだけではなく、その際に setter 関数内の処理も実行されることを意識しましょう。
#筆者は、それを忘れて、表示タイミングがずれるバグを直すことになりました。

今回の例では、メンバ変数の setter 関数内でカスタムシグナル発せられます。
そのカスタムシグナルの受信側のメソッドで、画面の数値の表示を更新しています。
そのメンバ変数への代入の前に、画面に表示される他のデータを全て更新していない場合、一部のデータだけが古い状態で画面に表示されます。
※具体例の説明については、スクリプトの _on_button_random_button_up 関数冒頭のコメントを参照してください。

getter, setter, signal はとても重要で便利な機能ですが、 setter を割り当てたメンバ変数へ値を代入する場合は、代入の他の処理も動作することを留意して、実装しましょう。

テスト

F6 キーで作成・保存した現在のシーンを実行します。

Godot4 StudySetterGetterSignal で作ったランダム(1~9)に数値が加算されていくゲーム

ボタンを押すと

  1. そのボタンの button_up シグナル受信側メソッドの関数の呼び出される
  2. その受信側メソッドで、メンバ変数の値変更される
  3. メンバ変数に割り当てた setter 用の関数でカスタムシグナルが発せられる
  4. カスタムシグナル接続 (connect) している関数が呼ばれ、画面表示更新される

という、値変更で呼ばれる setter 用の関数とカスタムシグナル連携によって、変数の値が変わったタイミングで画面表示を更新することができました。

Godot4 StudyGetterSetterSignal のシーン実行結果

まとめ

今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、作成したクラスのメンバ変数の値の設定を行う際に呼び出される setter 関数を利用して、メンバ変数の値が変更された際に接続済み関数を呼び出す独自のカスタムシグナルを実装したスクリプト例テストシーンの作成、その実行結果を紹介しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました