【Godot】カスタムリソースの作成と活用 - Godotで実現するデータ駆動設計

作成: 2025-12-08最終更新: 2026-07-09

Godotのカスタムリソース(Resource継承)でデータ駆動設計を実現する方法を解説。ロジックとデータの分離、インスペクタでの編集と.tres保存、継承による派生、duplicate()での実行時安全、JSON/CSV/SQLiteとの使い分けまで、図とともに学びます。

敵のステータスをスクリプトに直書きしていると、敵の種類を増やすたびにコードをコピペし、バランス調整のたびにコードを開いて数値を書き換える——そんな消耗を感じたことはないでしょうか。しかもプランナーやデザイナーは、コードを触れないと数値ひとつ変えられません。

この悩みを解くのが カスタムリソース(Custom Resource) です。Godotの Resource システムを拡張して独自のデータ型を作り、 ゲームのロジック(コード)とデータ(値)を分離 します。Unityの ScriptableObject に相当する、 データ駆動設計 の要です。

複数のデータカード(武器・防具・ポーションのステータス)が、それぞれのキャラクターやアイテムスロットに供給されるデータ駆動のイメージ

この記事でわかること

  • データ駆動設計 とは(ロジックとデータの分離)
  • Resource を継承した カスタムリソースの定義 とインスペクタ編集
  • 継承 で派生リソースを作る(ItemDataWeaponData
  • duplicate()実行時の変更を安全 に行う
  • JSON / CSV / SQLite との 使い分け

Sponsored

データ駆動設計とは

データ駆動設計とは、 「処理(ロジック)」と「値(データ)」を切り離す 考え方です。1つの汎用的なコードに、差し替え可能なデータを与えて、多彩なバリエーションを作ります。

1つのロジック(コード)が、戦士データ・魔法使いデータ・盗賊データという差し替え可能な複数のデータを読み込んで別々のキャラになる図

例えば「敵」を動かすコードは1つ。そこに「スライムのデータ」「ゴブリンのデータ」「ドラゴンのデータ」を差し替えて渡せば、同じコードが別々の敵になります。 データを直書きしない ことで、

  • 敵を増やすとき、コードでなく データファイルを増やすだけ で済む
  • バランス調整が、コードを開かず インスペクタで数値を触るだけ になる
  • プランナーやデザイナーも、コードを知らずにデータを編集できる

——と、開発がぐっと楽になります。この「データ」を担うのがカスタムリソースです。

カスタムリソースを定義して使う

カスタムリソースは、Resource を継承したスクリプトで 型を定義 し、その 値をインスペクタで編集 して、 .tres ファイルに保存 します。

カスタムリソースの流れ。コードでextends Resourceと@exportを定義し、インスペクタでcharacter_name/max_health/attack_powerを編集し、.tresで保存する図

まず、Resource を継承して @export でプロパティを並べます。class_name を付けると、グローバルな型として使えます。

# character_data.gd
class_name CharacterData
extends Resource

@export var character_name: String = "New Character"
@export var max_health: int = 100
@export var attack_power: float = 15.0

enum Job { WARRIOR, MAGE, ROGUE }
@export var job: Job = Job.WARRIOR         # enumはインスペクタで選択式になる

# データに紐づくロジックをメソッドで持たせることもできる
func get_description() -> String:
    return "%s / HP:%d / ATK:%.1f / %s" % [
        character_name, max_health, attack_power, Job.find_key(job)]

保存したら、FileSystemドックで右クリック →「新規作成」→「リソース」→ CharacterData を選び、player_data.tres などの名前で保存します。あとは、ノード側で 型として直接 受け取れます。

extends CharacterBody2D

@export var data: CharacterData      # インスペクタで.tresをドラッグして割り当てる

func _ready() -> void:
    if data:
        print(data.get_description())  # データに応じた振る舞い

@export var data: CharacterData のように 型を明示 できるので、インスペクタには CharacterData.tres しかドロップできず、型安全です。

Sponsored

実践:継承でアイテムデータベースを作る

カスタムリソースの強みが最も出るのが、 アイテムや敵のデータベース です。RPGの装備品、ローグライクの消費アイテム、カードゲームのカード——「共通の土台+種類ごとの違い」を、 継承 できれいに表現できます。

ItemData(item_name/icon/stackable)を基底に、WeaponData/PotionData/ArmorDataが継承して固有プロパティを追加する図

まず全アイテム共通の基底 ItemData を作ります。

# item_data.gd
class_name ItemData
extends Resource

@export var item_id: int = 0
@export var item_name: String = "Unknown Item"
@export_multiline var description: String = ""
@export var icon: Texture2D
@export var stackable: bool = true

武器やポーションには固有のデータが要ります。ItemData継承 して、足りない分だけ追加します。

# weapon_data.gd
class_name WeaponData
extends ItemData                 # ItemDataの全プロパティを引き継ぐ

@export var attack_bonus: float = 5.0   # 武器だけの追加プロパティ
@export var weapon_type: String = "Sword"

こうすると、WeaponDataitem_name などの共通項目を 持ったまま、武器固有の項目が増えます。読み込むときは、型で判別できます。

func load_item(path: String) -> ItemData:
    var res := ResourceLoader.load(path)
    if res is WeaponData:
        print("武器: 攻撃+%.1f" % res.attack_bonus)
    return res if res is ItemData else null

継承の考え方そのものは OOPデザインパターン の記事も参考になります。 共通は基底に、固有は派生に ——この整理で、アイテムが何種類増えても破綻しません。

duplicate()で実行時の変更を安全にする

1つ注意点があります。 リソースは共有されます 。同じ .tres を10体の敵に割り当てると、10体は 同じデータの実体 を見ています。ここで1体のHPを直接書き換えると——全員のHPが変わってしまいます。

元データを直接変更すると共有する全員に影響するが、duplicate()で複製を作りその複製を変更すれば元は無事、という対比図

実行時に個体ごとの値を変えたいときは、duplicate()複製を作り、その複製を変更 します。

func _ready() -> void:
    # 共有の元データではなく、自分専用の複製を持つ
    data = data.duplicate()
    # これ以降 data をいくら書き換えても、他の個体や元の.tresは無事
    data.max_health += 20

「敵ごとにHPを少しばらけさせたい」「拾ったポーションの残量を減らしたい」といった 個体差のある変更 は、必ず duplicate() してから行うのが鉄則です。逆に、全個体で共有したい設定(マスターデータ)は、複製せず共有のまま読むだけにします。

Sponsored

代替手段との使い分け

ゲームデータの持ち方は、カスタムリソース以外にもあります。規模と用途で選びます。

カスタムリソース(.tres エディタ統合)/JSON(外部ツール連携)/CSV(大量の単純データ)/SQLite(数千件のクエリ)の4つの使い分けの図
方法得意向く用途
カスタムリソースエディタ統合・型安全・再利用キャラ・アイテム・スキルなど構造化データ
JSON人が読み書きしやすい・エンジン非依存設定ファイル・外部ツール連携
CSV表計算で編集できる大量の単純レコード(セリフ集など)
SQLite大量データの高速クエリ数千件を超えるアイテム・ユーザーデータ

Godot内で完結する構造化データなら、まずカスタムリソース が第一候補です。外部ツールとやり取りするなら JSON、翻訳や大量のセリフはCSV、数千件規模のクエリが要るならSQLite、と使い分けます。

おまけ:先に知っておくと良いこと

  • .tres.res.tres はテキストで Gitと相性が良く 開発向き。.res はバイナリで ロードが速く軽い のでリリース向き。開発は .tres、出荷時に .res へ、が定番です。
  • 大量ロードは非同期で :起動時に全リソースを読むと重いので、ResourceLoader.load_threaded_request()非同期読み込み し、応答性を保ちます。
  • 変更の通知はシグナルで :リソース内の値が変わったことを他へ伝えたいなら、リソース内に シグナル を定義します。
  • セーブデータにも使える :プレイ状況をカスタムリソースに詰めて保存する手もあります。セーブ/ロードシステム で扱います。

まとめ

  • カスタムリソースResource を継承した独自データ型。ロジックとデータを分離する
  • class_name@export で型を定義し、値はインスペクタで編集、.tres に保存
  • 継承 で「共通は基底、固有は派生」に整理し、アイテム図鑑などを拡張しやすくする
  • duplicate() で複製してから変更すれば、共有データを壊さず個体差を出せる
  • 規模と用途で JSON / CSV / SQLite と使い分ける

まずはキャラの基本ステータスを CharacterData にして、インスペクタで数値をいじってみてください。「コードを触らずにゲームが変わる」感覚が掴めたら、データ駆動設計の第一歩です。

さらに学ぶために