このページでは Godot Engine 4.x系で、ゲームデータをセーブ・ロードする方法について説明をします。
目次
セーブデータの保存方法
セーブデータのファイル操作の基礎知識
ファイルの書き込みは以下の記述で行います。
extends Node2D
func _ready() -> void:
# ファイルを書き込みモードで開く.
var f = FileAccess.open("user://savedata.txt", FileAccess.WRITE)
# "test save" という文字を書き込む.
f.store_string("test save")
# ファイルを閉じる.
f.close()
FileAccess.open() がファイルを開く関数で、戻り値がファイルオブジェクトとなります。
ここで気になるのがファイルパスの謎の文字です。“user://” というのはそのアプリケーションが使用するフォルダで、環境によって以下のパスに保存されます。
- Windows: %APPDATA%\Godot\[プロジェクト名]
- macOS: ~/Library/Application Support/Godot/app_userdata/[プロジェクト名]
ただこれらのフォルダを開くのは少々手間なので、Godot には直接開くための機能が用意されています。
メニューから「プロジェクト > ユーザーデータフォルダを開く」を選びます。
するとユーザーデータフォルダが自動的に開いて、先ほどのファイル書き込み処理が正しく行われたことが確認できます。
保存したファイルを読み込むには以下のように記述します。
extends Node2D
## セーブデータのファイルパス.
const PATH_SAVEDATA = "user://savedata.txt"
func _ready() -> void:
if FileAccess.file_exists(PATH_SAVEDATA) == false:
print("セーブデータが存在しません: %s"%PATH_SAVEDATA)
return
var f = FileAccess.open(PATH_SAVEDATA, FileAccess.READ)
print(f.get_as_text())
# ファイルを閉じる.
f.close()
読み取りモードで開くだけなのですが、ファイルが存在しない可能性があるため FileAccess.file_exists() でファイルの存在チェックをしてから読み込みを行います。
複雑なデータ構造で保存する
セーブデータに保存する情報はゲームによって異なりますが、RPGやSLGを作るときなどはセーブする情報が複雑になります。
そこでセーブするデータの形式を何にするべきかですが、個人的には一般的によく使われている “JSON” 形式 はおすすめしません。
というのも Godot Engine には固有のシリアライズ機能が用意されているため、データの互換性として一番安定すると考えているためです。
具体的には var_to_str() / str_to_var() という関数を使用してデータを文字列に変換(または逆変換)します。
extends Node2D
## セーブデータのファイルパス.
const PATH_SAVEDATA = "user://savedata.txt"
func _ready() -> void:
# セーブ処理を呼び出す
_save()
## セーブを行う.
func _save() -> void:
# セーブデータを辞書型で定義.
var savedata = {}
# キャラデータ.
var hero = {} # 勇者のデータ.
hero["lv"] = 10
hero["name"] = "hero"
hero["hp"] = 100
hero["mp"] = 20
var magician = {} # 魔法使いのデータ.
magician["lv"] = 8
magician["name"] = "magician"
magician["hp"] = 50
magician["mp"] = 120
# キャラリスト
var chara_list = [hero, magician]
savedata["chara_list"] = chara_list
# セーブした座標.
savedata["pos"] = Vector2i(60, 89)
# ファイルを書き込みモードで開く.
var f = FileAccess.open(PATH_SAVEDATA, FileAccess.WRITE)
# セーブデータを文字列に変換.
var s = var_to_str(savedata)
f.store_string(s)
# ファイルを閉じる.
f.close()
これを実行すると以下のようなテキストデータとして保存されます。
{
"chara_list": [{
"hp": 100,
"lv": 10,
"mp": 20,
"name": "hero"
}, {
"hp": 50,
"lv": 8,
"mp": 120,
"name": "magician"
}],
"pos": Vector2i(60, 89)
}
読み込み方法のサンプルは以下のとおりです。
extends Node2D
## セーブデータのファイルパス.
const PATH_SAVEDATA = "user://savedata.txt"
func _ready() -> void:
# ロードを処理を呼び出す.
_load()
## ロードを行う.
func _load() -> void:
if FileAccess.file_exists(PATH_SAVEDATA) == false:
print("セーブデータが存在しません: %s"%PATH_SAVEDATA)
return
var f = FileAccess.open(PATH_SAVEDATA, FileAccess.READ)
var s = f.get_as_text()
# 文字列をセーブデータに変換.
var savedata = str_to_var(s)
print("セーブした座標:", savedata["pos"])
for chara in savedata["chara_list"]:
print("-------------")
print("lv: %d"%chara["lv"])
print("name: %s"%chara["name"])
print("hp: %s"%chara["hp"])
print("mp: %s"%chara["mp"])
# ファイルを閉じる.
f.close()
セーブした座標:(60, 89)
-------------
lv: 10
name: hero
hp: 100
mp: 20
-------------
lv: 8
name: magician
hp: 50
mp: 120