Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
リソース¶
ノードとリソース¶
ここまでのチュートリアルではGodotの、エンジンのほとんどの機能が頼りにしている、Node(ノード)クラスについて主に紹介してきました。もうひとつ、同じくらい重要なデータ型はResource(リソース)です。
Node は、機能を提供します。例えばスプライトや3Dモデルの表示、物理演算、ユーザーインターフェースの配置などです。一方、Resourceはデータの格納に使います。それ自身はなにもしませんが、代わりにノードが、データの入ったリソースを使用します。
Anything Godot saves or loads from disk is a resource. Be it a scene (a .tscn
or an .scn
file), an image, a script... Here are some Resource examples:
エンジンがリソースをディスクから読み込む際に、読み込むのは一度きりです。もしメモリ上にすでにリソースのコピーがあれば、読み込む代わりに毎回そのコピーを返します。リソースはデータのみを含むので、重複させても意味はないのです。
ノードとリソースにかかわらず、すべてのオブジェクトは、自身のプロパティをエクスポートできます。プロパティには、String、整数(int)、Vector2など、さまざまな種類がありますが、これらすべての型はリソースになることができます。つまり、ノードとリソースはいずれも、他のリソースをプロパティとして持てるのです。
外部と組み込みの比較¶
リソースを保存する方法はふたつあります。それは:
シーンの外部。個別のファイルとしてディスクに保存。
内蔵。使用する*.tscnあるいは*.scnファイルの中に保存。
To be more specific, here's a Texture2D in a Sprite2D node:
Clicking the resource preview allows us to view the resource's properties.
Pathプロパティはリソースの元々の場所を表しています。この例の場合は、元は robi.png
と名付けられたPNG画像です。このように、元がファイルであれば、外部リソースになります。Pathを消去するか、あるいはこの場所にない場合は、内部リソースになります。
リソースの内部と外部の切り替えは、シーンを保存するときに行われます。上記の例の場合、もしパス "res://robi.png"
を消去してから保存すると、Godotは画像を .tscn シーンファイルの内部に保存します。
注釈
もし内部リソースを保存した場合でも、複数のシーンをインスタンス化したときは、エンジンがそのコピーを読み込むのは一度だけです。
コードからリソースを読み込む¶
コードにてリソースを読み込む方法は、ふたつあります。ひとつ目は load()
関数で、いつでも使えます:
func _ready():
# Godot loads the Resource when it reads this very line.
var imported_resource = load("res://robi.png")
$sprite.texture = imported_resource
public override void _Ready()
{
// Godot loads the Resource when it executes this line.
var texture = GD.Load<Texture>("res://Robi.png");
var sprite = GetNode<Sprite2D>("sprite");
sprite.Texture = texture;
}
You can also preload
resources. Unlike load
, this function will read the
file from disk and load it at compile-time. As a result, you cannot call preload
with a variable path: you need to use a constant string.
func _ready():
# Godot loads the resource at compile-time
var imported_resource = preload("res://robi.png")
get_node("sprite").texture = imported_resource
// 'preload()' is unavailable in C Sharp.
シーンの読み込み¶
Scenes are also resources, but there is a catch. Scenes saved to disk are resources of type PackedScene. The scene is packed inside a Resource.
To get an instance of the scene, you have to use the PackedScene.instantiate() method.
func _on_shoot():
var bullet = preload("res://bullet.tscn").instantiate()
add_child(bullet)
private PackedScene _bulletScene = GD.Load<PackedScene>("res://Bullet.tscn");
private void OnShoot()
{
Node bullet = _bulletScene.Instantiate();
AddChild(bullet);
}
このメソッドは、シーンの階層どおりにノードを作成し、それらを設定してから、そのシーンのルートノードを返します。これは他のノードの子にすることができます。
The approach has several advantages. As the PackedScene.instantiate() function is fast, you can create new enemies, bullets, effects, etc. without having to load them again from disk each time. Remember that, as always, images, meshes, etc. are all shared between the scene instances.
リソースの解放¶
When a Resource is no longer in use, it will automatically free itself. Since, in most cases, Resources are contained in Nodes, when you free a node, the engine frees all the resources it owns as well if no other node uses them.
独自のリソースを作成¶
Godotの他のオブジェクトと同様に、ユーザーはリソースをスクリプト化することもできます。リソーススクリプトは、オブジェクトプロパティと、シリアル化されたテキストまたはバイナリデータ (*.tres, *.res) との間で、自由に変換できる機能を継承します。また同時に、参照型から参照カウントメモリ管理機能を継承します。
This comes with many distinct advantages over alternative data structures, such as JSON, CSV, or custom TXT files. Users can only import these assets as a Dictionary (JSON) or as a FileAccess to parse. What sets Resources apart is their inheritance of Object, RefCounted, and Resource features:
定数を定義できるため、他のデータフィールドまたはオブジェクトの定数は必要ありません。
プロパティの設定(setter)と取得(getter )用のメソッドを含むメソッドを定義できます。これにより、基になるデータの抽象化とカプセル化が可能になります。(カプセル化する事によって)リソーススクリプトの構造を変更する必要が発生した場合でも、そのリソースを使用するゲームをその都度それに合わせて変更する必要が無くなります。
シグナルを定義できるため、リソースは管理するデータの変更に対する応答をトリガーできます。
プロパティが定義されているため、ユーザーは自分のデータが存在することを100%知っています。
リソースの自動シリアル化と逆シリアル化は、 Godot エンジンの組み込み機能です。ユーザーは、リソース ファイルのデータをインポート/エクスポートするためにカスタム ロジックを実装する必要はありません。
リソースはサブリソースを再帰的にシリアル化することもできるため、ユーザーはさらに高度なデータ構造を設計できます。
ユーザーは、リソースをバージョン管理に適したテキストファイル(*.tres)として保存できます。ゲームをエクスポートすると、Godotはリソースファイルをバイナリファイル(*.res)としてシリアル化し、読書きの速度と圧縮率を向上させます。
Godotエンジンのインスペクタは、すぐに使用できるリソースファイルをレンダリングおよび編集します。そのため、多くの場合、ユーザーはデータを視覚化または編集するためにカスタムロジックを自分で実装する必要はありません。リソースに関するこの作業を行うには、ファイルシステムドックでリソースファイルをダブルクリックするか、インスペクタのフォルダアイコンをクリックして、ダイアログでファイルを開きます。
基本リソースだけでなく、その他のリソースタイプも拡張できます。
Godotを使用すると、インスペクタでカスタムリソースを簡単に作成できます。
インスペクタでプレーンなリソースオブジェクトを作成します。これは、スクリプトがその型を拡張可能なら、新たなリソースを派生させる原型にもできます。
インスペクタで
script
プロパティをスクリプトに設定します。
インスペクタにリソーススクリプトのカスタムプロパティが表示されます。これらの値を編集してリソースを保存すると、インスペクタはカスタム プロパティもシリアル化します。インスペクタからリソースを保存するには、インスペクタのツールメニュー(右上)をクリックし、「保存」または「名前を付けて保存」を選択します。
If the script's language supports script classes, then it streamlines the process. Defining a name for your script alone will add it to the Inspector's creation dialog. This will auto-add your script to the Resource object you create.
Let's see some examples.
Create a Resource and name it bot_stats
.
It should appear in your file tab with the full name bot_stats.tres
.
Without a script, it's useless, so let's add some data and logic!
Attach a script to it named bot_stats.gd
(or just create a new script, and then drag it to it).
extends Resource
@export var health: int
@export var sub_resource: Resource
@export var strings: PackedStringArray
# Make sure that every parameter has a default value.
# Otherwise, there will be problems with creating and editing
# your resource via the inspector.
func _init(p_health = 0, p_sub_resource = null, p_strings = []):
health = p_health
sub_resource = p_sub_resource
strings = p_strings
// BotStats.cs
using Godot;
namespace ExampleProject
{
public partial class BotStats : Resource
{
[Export]
public int Health { get; set; }
[Export]
public Resource SubResource { get; set; }
[Export]
public string[] Strings { get; set; }
// Make sure you provide a parameterless constructor.
// In C#, a parameterless constructor is different from a
// constructor with all default values.
// Without a parameterless constructor, Godot will have problems
// creating and editing your resource via the inspector.
public BotStats() : this(0, null, null) {}
public BotStats(int health, Resource subResource, string[] strings)
{
Health = health;
SubResource = subResource;
Strings = strings ?? System.Array.Empty<string>();
}
}
}
Now, create a CharacterBody3D, name it Bot
, and add the following script to it:
extends CharacterBody3D
@export var stats: Resource
func _ready():
# Uses an implicit, duck-typed interface for any 'health'-compatible resources.
if stats:
stats.health = 10
print(stats.health)
# Prints "10"
// Bot.cs
using Godot;
namespace ExampleProject
{
public partial class Bot : CharacterBody3D
{
[Export]
public Resource Stats;
public override void _Ready()
{
if (Stats is BotStats botStats)
{
GD.Print(botStats.Health); // Prints '10'.
}
}
}
}
Now, select the CharacterBody3D node which we named bot
, and drag&drop the bot_stats.tres
resource onto the Inspector. It should print 10! Obviously, this setup can be used for more advanced features than this, but as long you really understand how it all worked, you should figure out everything else related to Resources.
注釈
リソーススクリプトは、UnityのScriptableObjectsに似ています。インスペクタは、カスタムリソースの組み込みサポートを提供します。ですが、必要に応じて、ユーザーは独自のコントロールベースのツールスクリプトを設計し、それらを EditorPlugin と組み合わせて、データ用のカスタムビジュアライゼーションとエディタを作成することもできます。
Unreal Engine's DataTables and CurveTables are also easy to recreate with Resource scripts. DataTables are a String mapped to a custom struct, similar to a Dictionary mapping a String to a secondary custom Resource script.
# bot_stats_table.gd
extends Resource
const BotStats = preload("bot_stats.gd")
var data = {
"GodotBot": BotStats.new(10), # Creates instance with 10 health.
"DifferentBot": BotStats.new(20) # A different one with 20 health.
}
func _init():
print(data)
using Godot;
public partial class BotStatsTable : Resource
{
private Godot.Dictionary<string, BotStats> _stats = new Godot.Dictionary<string, BotStats>();
public BotStatsTable()
{
_stats["GodotBot"] = new BotStats(10); // Creates instance with 10 health.
_stats["DifferentBot"] = new BotStats(20); // A different one with 20 health.
GD.Print(_stats);
}
}
Instead of inlining the Dictionary values, one could also, alternatively:
Import a table of values from a spreadsheet and generate these key-value pairs.
Design a visualization within the editor and create a plugin that adds it to the Inspector when you open these types of Resources.
CurveTablesも同じですが、float値の配列または Curve/Curve2D リソースオブジェクトにマッピングされます。
警告
リソース ファイル (*.tres/*.res) は、使用するスクリプトのパスをファイルに格納します。リソース ファイルが読み込まれると、そのスクリプトをフェッチして型の拡張機能として読み込みます。スクリプトでサブクラス、つまりスクリプトの内部クラス (GDScript で class
キーワードを使用するなど) を割り当てようとしても、それは機能しません。Godot は、スクリプト サブクラスのカスタム プロパティを正しくシリアル化しません。
以下の例では、Godotは Node
スクリプトを読み込み、それが Resource
を拡張していないことを確認して、互換性がないタイプなので、スクリプトがリソースオブジェクトのロードに失敗したと判断します。
extends Node
class MyResource:
extends Resource
@export var value = 5
func _ready():
var my_res = MyResource.new()
# This will NOT serialize the 'value' property.
ResourceSaver.save(my_res, "res://my_res.tres")
using Godot;
public partial class MyNode : Node
{
public partial class MyResource : Resource
{
[Export]
public int Value { get; set; } = 5;
}
public override void _Ready()
{
var res = new MyResource();
// This will NOT serialize the 'Value' property.
ResourceSaver.Save(res, "res://MyRes.tres");
}
}