Godot4 preloadとclass_nameによる疑似的名前空間の実装例

GodotEngine4 でスクリプトファイルにグローバルクラスの名前割り当てられる class_name と、スクリプトリソースを GDScript オブジェクトとして扱える preload 関数を用いて、class_name を設定していないスクリプトファイルを、グローバルクラスと変数で、疑似的な名前空間階層的に作成してアクセスするスクリプト例と実行結果を紹介します。

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

前回の記事

前回は、バージョンが異なる、同じファイル名のスクリプトファイルのパスを指定した preload 関数で取得した GDScript リソースクラスのオブジェクトを介して、そのスクリプトの静的関数を呼び出しました。

class_name によるグローバルクラスの登録は、2つのスクリプトファイルで、同じクラス名は指定できずエラーが発生することを確認しました。

Godot4 preload による疑似的な名前空間の実装例4

res://study/pseudo_namespace_with_preload/submodule_v2/my_submodule.gd:2 – Parse Error: Class “MySubmodule” hides a global script class.

class_name でグローバルクラス名だけでアクセスする

GodotEngine には、前回紹介した preload 関数で取得した GDScript オブジェクトを変数に格納して、それをクラス名のように扱う方法のほかに、外部ファイルからでもクラス名を介してアクセスできるグローバルクラスがあります。
class_name を用いることで、スクリプトファイル単位グローバルクラス定義できます。
※同じクラス名は重複して使うことはできません。

You can use any class, including your custom classes, as types. There are two ways to use them in scripts. The first method is to preload the script you want to use as a type in a constant:

カスタム クラスを含む任意のクラスを型として使用できます。スクリプトでこれらを使用するには 2 つの方法があります。最初の方法は、定数の型として使用するスクリプトをプリロードすることです。

const Rifle = preload("res://player/weapons/rifle.gd")
var my_rifle: Rifle

The second method is to use the class_name keyword when you create. For the example above, your rifle.gd would look like this:

2 番目の方法は、作成時に class_name キーワードを使用することです。上の例の場合、rifle.gd は次のようになります。

class_name Rifle
extends Node2D
静的型付けGDScript — Godot Engine (4.x)の日本語のドキュメント

実装例

以下は、後述するファイルで class_name で定義したグローバルクラス名(例では MySubmodule)と、その内部の GDScript オブジェクト変数名から、その gd スクリプトの場所を意識せず静的関数を呼び出すスクリプト例です。
スクリプトの作成は、ファイルシステムドックで右クリックして表示されるメニュー「新規作成」→「スクリプト」で行えます。

extends Node

# preload と class_name による疑似的な名前空間のテスト用のコードです。
# 同じフォルダにある同じ名前のシーンファイルを選択して F6 キーなどで起動すると実行されます。

# Called when the node enters the scene tree for the first time.
func _ready():
	# グローバルクラスでバージョンの異なる静的関数を呼び出します。
	MySubmodule.V1.greet()  # Hello. Ver.1
	MySubmodule.V2.greet()  # Hello. Ver.2
	return

以下は、グローバルクラス名(例では MySubmodule)を class_name で定義して外部からはそのグローバルクラス名だけでアクセスできるようにしたスクリプトファイルです。
その中では、class_name を定義していないスクリプトファイルpreload 関数で読み込み、 const によって外部からアクセスできる静的変数として GDScript オブジェクトを保持しています。

extends Object
class_name MySubmodule

## class_name で定義したグローバルクラスの名前と組み合わせて、
## 各スクリプトの静的関数を呼び出すための変数を提供します。
const V1 := preload("../submodule_v1/my_submodule.gd")
const V2 := preload("../submodule_v2/my_submodule.gd")

以下は、上記のスクリプトから preload 関数で読み込まれる GD スクリプトファイルです。
それぞれ、固定の文字列を出力します。Ver のあと番号だけが異なります。

extends Node

static func greet() -> void:
	print("Hello. Ver.1")
	return
extends Node

static func greet() -> void:
	print("Hello. Ver.2")
	return

前述の pseudo_namespece_with_preload.gd スクリプトを、作成した空のシーン(例では pseudo_namespece_with_preload.tscn)に割り当て保存します。
シーンの作成は、ファイルシステムドックで右クリックして表示されるメニュー「新規作成」→「シーン」で行えます。

Godot4 preload による疑似的な名前空間の実装例3

実行結果

先ほどスクリプトを割り当てたシーンを選択して F6 キー実行すると、class_name で定義したグローバルクラス名とそのスクリプト内の GDScript オブジェクトの静的変数名の組み合わせで、疑似的な名前空間のようなアクセスの仕方で静的関数を呼び出せました。

preload したスクリプトと class_name を用いた疑似的名前空間1
Hello. Ver.1
Hello. Ver.2
--- Debugging process stopped ---

今回は、グローバルクラス名と GDScript オブジェクトの変数名の組み合わせでしたが、さらに GDScript オブジェクト内(例では V1, V2)に、GDScript オブジェクト変数を置くことで階層的なアクセス(MySubmodule.V1.Image.draw_image() など)も可能だと思います。

まとめ

  • class_name で定義したグローバルクラス名とそのスクリプト内の GDScript オブジェクトの静的変数名の組み合わせで、疑似的な名前空間のようなアクセスの仕方で静的関数を呼び出しました。

参照サイト 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をコピーしました