概要
ゲーム開発を進めていくと、「プレイヤーのHPや装備を次のステージに引き継ぎたい」「集めたアイテムの情報を保持したい」「ゲーム全体の設定を一元管理したい」といった要求が出てきます。しかし、change_scene_to_file()でシーンを切り替えると、デフォルトでは古いシーンの情報はすべて破棄されてしまいます。
この問題を解決し、シーンをまたいでデータを永続的に保持するための最も標準的で強力な方法が、Autoload(オートロード) 機能です。これは、ソフトウェア設計で広く知られる「シングルトン」パターンを、Godotがエンジンレベルでサポートし、簡単に利用できるようにした仕組みです。
この記事では、基本的な設定方法から、より実践的なコード例、よくある間違いとベストプラクティス、そしてAutoload以外のデータ共有方法との比較まで解説します。
Autoload(シングルトン)とは
Autoloadとは、ゲームの起動時にGodotが自動的にインスタンス化し、シーンツリーのルートに常駐させるノードまたはスクリプトのことです。一度Autoloadに登録されると、ゲームが終了するまでメモリ上に存在し続けるため、どのシーンのどのスクリプトからでも、グローバル変数のように直接アクセスできるようになります。
この「どこからでもアクセスできる単一のインスタンス」という性質を持つデザインパターンを、一般的にシングルトン (Singleton) と呼びます。
主な用途
Autoloadは、以下のような「ゲーム全体で共有・管理したい」要素に最適です。
- グローバルな状態管理: プレイヤーのスコア、所持金、ライフ、インベントリなど、ゲームの進行状況に関わる情報。
- 汎用的な機能の提供: サウンドマネージャー、シーン遷移時のフェードエフェクト、HTTPリクエスト管理など、どこからでも呼び出したい共通機能。
- システムの管理: ゲーム全体の進行を司るマネージ ャー、イベントシステム(シグナルバス)など、アプリケーションの根幹をなす機能。
Autoloadの基本的な設定方法
Autoloadの設定は、プロジェクト設定からわずか数ステップで完了します。
1. グローバルスクリプトの作成
まず、管理したいデータや機能を持つスクリプトを作成します。ここでは、プレイヤーのデータとゲーム設定を管理するPlayerData.gdというスクリプトを例に挙げます。
# PlayerData.gd
extends Node
# プレイヤーの基本情報
var player_name: String = "Hero"
var health: int = 100
var max_health: int = 100
# ゲームの進行状況
var score: int = 0
var high_score: int = 0
# 宝箱の開封状態を管理する辞書
# キー: "SceneName_ChestID", 値: bool (trueなら開封済み)
var opened_chests: Dictionary = {}
func add_score(amount: int) -> void:
score += amount
if score > high_score:
high_score = score
func take_damage(amount: int) -> void:
health -= amount
if health < 0:
health = 0
func is_chest_opened(chest_id: String) -> bool:
return opened_chests.has(chest_id)
func mark_chest_as_opened(chest_id: String) -> void:
opened_chests[chest_id] = true
2. プロジェクト設定から登録
- メニューバーから 「プロジェクト」→「プロジェクト設定」 を選択します。
- 上部のタブから 「Autoload」 を選択します。
- 「パス」 の入力欄の横にあるフォルダアイコンをクリックし、先ほど作成した
PlayerData.gdを選択します。 - 「ノード名」 は自動的にスクリプト名と同じ
PlayerDataになります。これがグローバルアクセスのための名前になります。 - 「追加」 ボタンを押して登録します。

これで設定は完了です。ゲームを実行すると、Godotは自動的にPlayerData.gdをインスタンス化し、PlayerDataという名前でアクセスできるようにしてくれます。
スクリプトからのアクセス方法
Autoloadに登録したノードは、登録した「ノード名」がそのままグローバル変数のように機能します。どのスクリプトからでも、事前のget_node()や@onreadyによる参照取得なしに、直接アクセスできます。
具体的なコード例
敵を倒してス コアを加算する
# Enemy.gd
func die():
# PlayerDataの関数を直接呼び出す
PlayerData.add_score(100)
print("現在のスコア: ", PlayerData.score)
queue_free()
宝箱を開ける処理
# TreasureChest.gd
@export var chest_id: String = "level1_gold_chest"
func _ready():
# すでに開封済みか確認し、見た目を変える
if PlayerData.is_chest_opened(chest_id):
$Sprite2D.frame = 1 # 開いたスプライトに
is_open = true
func open():
if is_open: return
# PlayerDataに開封済みであることを記録
PlayerData.mark_chest_as_opened(chest_id)
# 中身を出す処理...
print("宝箱を開けた!")
UIにハイスコアを表示する
# GameOverScreen.gd
func _ready():
# PlayerDataの変数を直接参照する
$HighScoreLabel.text = "ハイスコア: %d" % PlayerData.high_score
このように、PlayerDataという名前でどこからでもアクセスできるため、シーンをまたいだデータの受け渡しが非常にシンプルになります。
よくある間違いとベストプラクティス
Autoloadは非常に便利ですが、使い方を誤るとプロジェクトの構造を複雑にし、メンテナンス性を著しく低下させる原因にもなります。
| よくある間違い | ベストプラクティス |
|---|