【Godot4.4】リソース(Resource)の基本と活用例

GodotEngine

この記事では、Godotにおけるリソース(Resource)の基本とその活用例についてまとめています。

リソース(Resource)概要

GodotにおけるResourceは、データの保存と再利用を実現する重要な仕組みです。
シーン (Node) とは異なり、ゲームのロジックやエディタ内のデータ管理を効率的に行うためのクラスで、以下のような特徴があります。

Resourceの特徴
  • シリアライズ可能: .tres.res 形式で保存でき、エディタ内で編集可能。
  • 参照型: Resource は参照として扱われ、同じリソースを複数のオブジェクトで共有可能。
  • カスタマイズ可能: class_name を使用して独自の Resource を作成できる。
  • スクリプトに埋め込み可能: スクリプト内で Resource を簡単に作成し、データ管理が容易になる。

Godotにおいて、エディタ「ファイルシステム」に表示されている各要素は、既存/自作を問わず、
すべてResource (正確には、Resourceクラスを継承した固有タイプリソース)であるといえます。

以下公式リファレンスページを見ると、Resourceクラスがすべての固有リソースから継承されていることが分かります。

Resource
Inherits: RefCounted< Object Inherited By: Animation, AnimationLibrary, AnimationNode, AnimationNodeStateMachinePlayback...

リソースの読み込み(load/preload)

例えば、Texture2DAudioStream などは Resource の一種であり、スプライトやサウンドを設定する際に利用されます。
リソースをコードから読み込む場合は、load() または preload() メソッドを使用します。

@onready var sprite = $Sprite2D

func _ready():
	var texture = load("res://icon.svg") as Texture2D
	sprite.texture = texture

以下のような構成で実行してみると、シーン実行時に画像が読み込まれることを確認できます。

load と preload の違いと使い分け

load、preloadはどちらもリソースの読み込みが可能なメソッドですが、以下のような特徴があります。

5.1 load() の特徴

  • 実行時にリソースをロードする。
  • null を返す可能性があるため、エラーハンドリングが必要。
  • 動的にリソースをロードしたい場合に適している。
var texture = load("res://textures/player.png") as Texture2D
sprite.texture = texture

5.2 preload() の特徴

  • コンパイル時にリソースをロードする。
  • load() に比べて処理が高速。
  • 事前に使用するリソースが分かっている場合に適している。
const PLAYER_TEXTURE = preload("res://textures/player.png")

func _ready():
    sprite.texture = PLAYER_TEXTURE

5.3 使い分けのポイント

load,preloadの違いをまとめると、以下のようになります。

相違点load()preload()
ロードのタイミングスクリプト実行時コンパイル時
パフォーマンス遅い (実行時にロード)速い (事前にロード)
エラーハンドリング必要
(存在しない場合nullが返る)
不要
(エラー時はコンパイル自体が失敗)
動的ロード可能不可

シーンの読み込み

保存したシーンは、PackedSceneというリソースの形式で扱うことができ、以下のようにロードして使用します。
 ① preload で、シーンをロード
 ➁ <PackedScene>.instantiate() で、シーンインスタンスを作成
 ③ add_child(<シーンインスタンス>) で、ノードツリーにシーンインスタンスを追加

func _ready():
	var enemy_scene = preload("res://enemy01.tscn").instantiate()
	add_child(enemy_scene)

以下のような構成で実行し、実行中にリモートから確認すると、シーンが追加されていることを確認できます。

新規リソースの作成と使用

Godotのエディタ上で Resource を作成するには、ファイルシステムで
右クリック > 新規作成 > リソース をクリックし、作成するリソースの型を選択します。

リソースファイルの保存場所と名前を設定すると、新規リソースが作成されます。

カスタムリソースの作成

作成したリソースにスクリプトをアタッチすることで、カスタムリソース(自作リソース)を作成・定義することもできます
基本的なカスタムリソースの作成手順・使用は以下の通りです。

① カスタムリソース用のスクリプトを作成 (例では、Resourceクラスを継承)

例ではプレイヤーのステータスを設定するリソースの想定で、以下のように@exportを使用し、ステータスのパラメータを変更できるようにインスペクター表示しています。

extends Resource
class_name PlayerStats

@export var health: int = 100
@export var attack: int = 20
@export var defense: int = 10

また、class_name を使用してResourceを継承したクラスとして定義することで、新規リソースを作成する際、以下のように選択が可能になります。(必須ではありません)

→この選択で作成した場合、そのリソースにはデフォルトで対応するスクリプトがアタッチされた状態で作成されます。

新規Resourceを作成し、①のスクリプトをアタッチします

→スクリプトをアタッチすると、@exportで表示設定した変数がインスペクターあることを確認できます。

自作Resourceによるデータ管理には、一般的なデータファイル(JSONやCSV、TXTなど)と比較した時に、
以下のような利点があります。

  • Object、RefCounted、Resourceの機能を継承している(関連するメソッド等を利用可能)
  • 独自に定数やシグナル、プロパティ定義可能。(他から参照する必要が無く、エンジンとしても認識できる)
  • プロパティのセッター/ゲッター・メソッドを含むメソッドを定義が可能。
    → データ構造のを抽象化/カプセル化が可能で、変更時はResourceスクリプトを編集するだけで、そのデータを使用したいゲームオブジェクトの動作に改修が不要になる
  • ResourceはGodotの標準機能であるため、各種データ処理やエディタ上での編集の面でも有利
    (リソースファイルはまず、バージョン管理に適したテキストファイル(.tres)として保存され、
    ゲームのエクスポート時には、バイナリファイル (.res) としてシリアライズし、高速化と圧縮を実行)

カスタムリソースの使用と注意点

作成したカスタムリソースは、例えば以下のように使用できます。

@export var status:PlayerStats    # 作成したカスタムリソースの型(またはResource でも可)で受付

func _ready():
	print("HP :",status.health)
	print("DEF:",status.attack)
	print("ATK:",status.defense)

上記スクリプトのアタッチされたノードのインスペクターで、status変数にカスタムリソースをアタッチすることで、以下のようにリソースの編集と出力結果の確認が可能です。

Resourceの注意点と対応

Resource は参照型であるため、1つの Resource を変更すると、それを参照している全てのオブジェクトに影響が及びます

そのため、アイテムや敵など、同じデータ構造で違うパラメータを与えたい場合は、Resource.duplicate() メソッドを使用し、同リソースの複製を使用するのが一般的です。

以下の例では、PlayerStatusリソースの複製を new_status 変数に格納し、その変数を使用して値の変更と出力を行っています。こうすることで、元のリソースに影響を与えずに、ここで使用したいステータスデータの編集が可能です。

@export var status:PlayerStats

func _ready():
	var new_status = status.duplicate()
	new_status.health += 100
	print("HP :",new_status.health)
コメント
コメント

要は、「リソースの値は直接変更しない」が原則で、
変動する値を扱う場合は、コピーを作成 or 別の変数にデータだけもらう といった対応になります

Resourceの活用例

使用のイメージをおさえるため、いくつかResourceを活用した処理の実装例を挙げてみます。

データのプリセット管理

例えば、RPGの敵キャラクターのステータスを Resource として定義し、敵ごとに異なるデータを管理できます。

extends Resource
class_name EnemyData

@export var name: String
@export var health: int
@export var attack: int
@export var defense: int

これを複数作成し、敵のスクリプトで活用できます。

@export var enemy_data: EnemyData

func _ready():
    var new_enemy_data = enemy_data.duplicate()  # 個別ステータスを設定するため、複製
    new_enemy_data.name = "E01"
    new_enemy_data.health = 100
    print("Enemy Name: " + new_enemy_data.name)    # 出力結果:E01
    print("Health: " + str(new_enemy_data.health)) # 出力結果:100
コメント
コメント

このようなケースでは、上記のようにduplicate()で複製するほか、
tresファイル自体をを複製し、個別にアタッチする方法もあります。

設定ファイルとしての使用

Resource を設定ファイルとして利用することで、ゲーム全体の設定を管理できます。(主にデフォルト値として使用)

extends Resource
class_name GameSettings

@export var volume: float = 1.0
@export var difficulty: int = 2

これを res://settings.tres として保存し、ゲーム開始時に読み込めば設定を適用できます。

var settings = load("res://settings.tres") as GameSettings
AudioServer.set_bus_volume_db(0, settings.volume)
print("音量設定:",AudioServer.get_bus_volume_db(0))  # 出力結果「 音量設定:1.0 」

スキルシステムの実装

ゲームのスキルシステムを Resource で管理すると、データの管理がしやすくなります。

extends Resource
class_name SkillData

@export var skill_name: String
@export var damage: int
@export var cooldown: float

スキルのリストを Resource 配列として管理することもできます。

@export var skills: Array[SkillData]

以下のように、インスペクター出力したリスト変数では、新規リソースデータを作成する形でスキルリソースをアタッチしていくと、個別の設定情報を保持してリスト管理が可能です。

おわりに

今回の記事では、Godotにおけるリソース(Resource)の基本とその活用例についてまとめました。
リソースは、データの再利用性と抽象化の面で非常に有用な機能で、開発効率の面でも重要な機能です。

より詳細な情報やその他のチュートリアルについては、以下公式ドキュメントのクラスリファレンスやチュートリアルページもご参照ください。

おすすめの本①
おすすめの本➁(Godot)
GodotEngineゲームエンジン
ひらまめ(hiramame)をフォローする

コメント

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