Godot4 同名の GD スクリプトファイルの関数を使い分ける実装例

GodotEngine4preload 関数を用いて、同じ名前の複数のスクリプトファイル使い分けるスクリプトとその実行結果を紹介します。
例えば、異なるバージョンの同名のスクリプトファイルを複数使いたい場合などに利用できます。
また、この実装例で発生する制限事項についても紹介します。

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

preload 関数とは

preload 関数は、指定したパスのリソースを取得します。

Resource preload(path: String

Returns a Resource from the filesystem located at path. During run-time, the resource is loaded when the script is being parsed. This function effectively acts as a reference to that resource. Note that this function requires path to be a constant String. If you want to load a resource from a dynamic/variable path, use load().

パスにあるファイルシステムからリソースを返します。実行時、スクリプトが解析されるときにリソースがロードされます。この関数は、そのリソースへの参照として効果的に機能します。この関数では、パスが定数の文字列である必要があることに注意してください。動的/変数パスからリソースを読み込む場合は、load() を使用します。

Note: Resource paths can be obtained by right-clicking on a resource in the Assets Panel and choosing “Copy Path”, or by dragging the file from the FileSystem dock into the current script.

注: リソース パスは、アセット パネルでリソースを右クリックして [パスのコピー] を選択するか、ファイルシステム ドックから現在のスクリプトにファイルをドラッグすることで取得できます。

@GDScript — Godot Engine (4.x)の日本語のドキュメント #preload と Google 翻訳

Resouece は、シーンやスクリプトなどのさまざまなリソースの基底クラスです。

Resource is the base class for all Godot-specific resource types, serving primarily as data containers. Since they inherit from RefCounted, resources are reference-counted and freed when no longer in use. They can also be nested within other resources, and saved on disk. PackedScene, one of the most common Objects in a Godot project, is also a resource, uniquely capable of storing and instantiating the Nodes it contains as many times as desired.

Resource は、すべての Godot 固有のリソース タイプの基本クラスであり、主にデータ コンテナとして機能します。これらは RefCounted から継承するため、リソースは参照カウントされ、使用されなくなったら解放されます。他のリソース内にネストしてディスクに保存することもできます。 Godot プロジェクトで最も一般的なオブジェクトの 1 つである PackedScene もリソースであり、含まれるノードを必要に応じて何度でも保存およびインスタンス化できる独自の機能があります。

Resource — Godot Engine (4.x)の日本語のドキュメント と Google 翻訳

gd スクリプトファイルを preload 関数で指定して得られるリソースは、リソースの派生クラス GDScript クラスであることを is で判定して確認しました。
※ is 判定については後述のプログラムと実行結果を参照してください。

A script implemented in the GDScript programming language, saved with the .gd extension. The script extends the functionality of all objects that instantiate it.

GDScript プログラミング言語で実装されたスクリプト。拡張子 .gd で保存されます。スクリプトは、それをインスタンス化するすべてのオブジェクトの機能を拡張します。

GDScript — Godot Engine (4.x)の日本語のドキュメント と Google 翻訳

リソースのパスは、ファイルシステムドックで、対象のファイル右クリックして表示されるメニュー「パスをコピー」でクリップボードにコピーされます。
※下図のファイルの場合は、「res://study/pseudo_namespace_with_preload/submodule_v1/my_submodule.gd」がコピーされました。

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

preload 関数は、事前に行われます。
必要になったタイミングでリソースを読み込む場合は load 関数を使用します。

GDScript には、グローバル preload メソッドが存在します。”読み込み” 処理を前もって行い、パフォーマンスに敏感なコードの途中で、リソースの読み込が発生することを回避するために、できるだけ早くリソースを読み込みます。

対応する load メソッドは、load ステートメントに到達したときにのみリソースをロードします。つまりリソースをその場でロードするため、リアルタイム性の高いプロセスの途中で行うと速度低下を引き起こす可能性があります。 load() 関数は、すべてのスクリプト言語からアクセスできる ResourceLoader.load(path) のエイリアスでもあります。

ロジックの設定 — Godot Engine (4.x)の日本語のドキュメント

実装例

以下は、 preload 関数による同名スクリプトファイルの使い分けのスクリプト例です。
スクリプトの作成は、ファイルシステムドックで右クリックして表示されるメニュー「新規作成」→「スクリプト」で行えます。

7 ~ 8 行目で、 preload 関数を用いて各フォルダの同名のスクリプトファイルを(例では my_submodule.gd )を GDScript リソースクラスのオブジェクトとして変数に格納しています。
var ではなく const のほうが良いかもしれません。

その格納した変数を用いて 15 ~ 16 行目で、各スクリプトの関数(例では greet )を呼び出しています。

gd スクリプトファイルのパスを指定した preload 関数の戻り値の型が GDScript リソースクラスであることは 12 行目の is で判定し、型が GDScript リソースクラスだった場合は、 print 文の内容が出力されます。

extends Node

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

# 別のフォルダにある同じ名前のファイルを読み込みます。
var MySubmoduleV1 := preload("./submodule_v1/my_submodule.gd")
var MySubmoduleV2 := preload("./submodule_v2/my_submodule.gd")

# Called when the node enters the scene tree for the first time.
func _ready():
	if MySubmoduleV1 is GDScript:
		print("MySubmoduleV1 is GDScript")
	# 同じ名前の静的関数を呼び出します。
	MySubmoduleV1.greet() # Hello. Ver.1
	MySubmoduleV2.greet() # Hello. Ver.2
	return

以下は、上記のスクリプトから 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 キー実行すると、preload 関数で読み込んだ同名の異なるスクリプトファイルの関数が実行され、それぞれ異なる出力を確認できました。
また、 is により、 GD スクリプトファイルを指定して preload 関数で得られるオブジェクトの型が GDScript リソースクラスであることも確認できました。

Godot4 preload による疑似的な名前空間の実装例2
MySubmoduleV1 is GDScript
Hello. Ver.1
Hello. Ver.2
--- Debugging process stopped ---

class_name が使用できない問題点

スクリプトをグローバルクラスとして定義する class_name は、同じ名前を使用できないため、複数のファイルに同じ名前の class_name が指定されるとエラーになります。

class_name

スクリプトを名前を持つグローバルにアクセス可能なクラスとして定義します。 Registering named classes を参照。

GDScriptリファレンス — Godot Engine (4.x)の日本語のドキュメント

今回の場合は、別フォルダにある各 my_submodule.gd に class_name MySubmodule の行を追加して、同じクラス名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 で同じクラス名を指定することはできません

まとめ

  • スクリプトファイルのパスを指定した preload 関数で取得した GDScript リソースクラスのオブジェクトを介して、そのスクリプトの静的関数を呼び出しました。
  • class_name によるグローバルクラスの登録は、同じクラス名では行えずエラーが発生することを確認しました。

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