所持金を300まで増やしても、Playを止めると次は0から。ゲームを閉じても続きから遊べるようにするには、実行中の値をファイルへ残す必要があります。
そのために使うのが Save Game です。残したい値を「持ち出し用の箱」へ写して保存し、次回は箱から取り出してゲームへ戻します。箱へ値を入れるところと、ファイルに書くところは別の処理です。
まずは所持金1項目で、この往復を作ってみましょう。300を保存し、900へ変えてからロードすると300に戻る。さらにPlayを止めてやり直しても、保存した300を取り出せるところまで確認します。
この記事でわかること
- Save Gameの型と、値を入れるオブジェクトを作る
- 現在の所持金を保存し、成功したかを確かめる
- ロードした値をゲームへ戻し、読めない場合も処理する
- Playをやり直して、ファイルに残ったことを確認する
Blueprintで変数とノードを作ったことがある人向けです。実践は1人用のローカルなセーブで、確認用Actorとキー入力を使います。
仕組み:ゲームの値・保存用の箱・ファイル
今回、所持金は次の3か所に登場します。
| 場所 | 今回の名前 | 役割 |
|---|---|---|
| ゲーム内の値 | ActorのGold | 今プレイしている所持金 |
| 保存用の箱 | BP_DemoSaveのSavedGold | 保存するときの値を写しておく |
| セーブファイル | NotesSaveDemo01のスロット | Playを止めた後も値を残す |

スロット は、保存先を区別する名前です。この記事では NotesSaveDemo01 を使います。同じ名前へもう一度保存すると、そのスロットの内容を更 新します。別の名前を使えば、別の記録として残せます。
Save Gameの箱を作っただけでは、まだファイルになっていません。また、ファイルを読んだだけでは、ActorのGoldは変わりません。保存するときも、読み戻すときも、値を写す処理を自分でつなぐ のが要点です。保存とロードの公式説明
準備:所持金を変えて表示する
1. 保存用の型BP_DemoSaveを作る
コンテンツブラウザの右クリックから「Blueprint Class」を選びます。親クラスの選択で「All Classes」を開き、SaveGame を検索して選択してください。名前を BP_DemoSave にします。
他のエンジンでいうと: Save Game は「保存する値をまとめたオブジェクト」です。Unity なら自前の JSON / バイナリ保存、Godot なら
FileAccessやResourceSaverに当たります。PlayerPrefsやConfigFileは、音量などの小さな設定向けです。
開いたら、次の変数を1つ追加し、コンパイルして保存します。
| 変数名 | 型 | 初期値 |
|---|---|---|
| SavedGold | Integer | 0 |
今回は、保存する項目を決めた 型 を作っています。この型から、実際に値を入れる箱をセーブ時に作ります。BP_DemoSaveをレベルへ置く操作はありません。
2. 確認用のActor、BP_SaveDemoを作る
親が「Actor」のBlueprintを作り、BP_SaveDemo と名付けます。次の3変数を追加してください。
| 変数名 | 型 | 初期値 | 用途 |
|---|---|---|---|
| Gold | Integer | 0 | 現在の所持金 |
| SaveRef | BP_DemoSaveのObject Reference | None | 保存用に作った箱を指しておく |
| SlotName | String | NotesSaveDemo01 | 保存・ロードで使う共通のスロット名 |
参照(Reference) は、作ったオブジェクトを後から指定するためのものです。SaveRefには箱そのもののコピーではなく、「今作ったこの箱を使う」という指定を持たせます。初期値のNoneは、まだ箱を指していない状態です。型はClass Referenceではなく、Object Referenceを選んでください。
「Class Defaults」で Auto Receive Input を「Player 0」にします。このActorが、1人目のプレイヤーのキー入力を受け取るための設定です。コンパイル・保存し、レベルへ BP_SaveDemo を 1個だけ 配置します。見た目のコンポーネントは不要です。
3. 所持金を表示するShowGoldを作る
BP_SaveDemoのイベントグラフで「Add Custom Event」を選び、ShowGold という名前にします。ほかの処理から呼び出せる「現在の所持金を表示する処理」です。
まず、Gold変数をグラフへドラッグして「Get」を選びます。値を文章へ入れる Format Text を追加し、「Format」に次を入力してください。
所持金: {Gold}
増えた「Gold」入力に、GoldのGetをつなぎます。図の色付きの線は値を渡す接続、白い線は処理を進める順番です。GetやFormat Textは値を読む・組み立てるだけなので、白い実行線はつなぎません。

次に Print Text を置き、ShowGoldの白い実行出力をつなぎます。Format Textの「Result」は、Print Textの「In Text」へ渡してください。

Print Textの詳細ピンを開き、「Print to Screen」「Print to Log」を有効、「Duration」を10、「Key」を GoldStatus にします。画面とログへ出力し、画面上では10秒間表示する設定です。同じKeyを使うと、前の所持金表示を新しい値で置き換えられます。これは表示用の名前で、保存先のスロットとは別です。
Event BeginPlay からもShowGoldを呼び、開始時の値を表示するようにします。グラフの右クリックで ShowGold を検索し、呼び出しノードを置いてつなぎます。
4. 確認用の2つの値を用意する
数字キーの 1 と 4 のイベントを置きます。テンキーではなく、キーボード上段の数字キーを選んでください。
1 の「Pressed」から Set Gold へつなぎ、値を300にします。その後でShowGoldを呼びます。4 側も同じようにつなぎ、こちらは900にしてください。ここでは保存と ロードの結果を比べるため、決まった2つの値を使います。

コンパイルしてPlayし、ゲーム画面をクリックします。最初は 所持金: 0、1 で300、4 で900になれば準備完了です。この段階ではファイルへ保存していないので、Playし直すと0へ戻ります。
セーブ:今の値を箱へ入れて書き出す
1. 保存用の箱を作る
BP_SaveDemoで数字キー 2 のイベントを追加します。「Pressed」から Create Save Game Object をつなぎ、「Save Game Class」に BP_DemoSave を指定してください。
「Return Value」を Set SaveRef の値へ渡し、白い実行線もつなぎます。これで、作った箱をSaveRefから指定できます。

この「Return Value」は、ノードが作った箱 を返す出力です。まだ保存ファイルは作られていません。Create Save Game Objectの公式API
2. GoldをSavedGoldへ写す
SaveRefのGetからドラッグし、Set Saved Gold を作ります。「Target」にSaveRef、「Saved Gold」の値にGoldのGetをつなぎます。白い実行線は、前の手順のSet SaveRefからつないでください。

Goldはゲーム側、SavedGoldは保存用の箱の中 です。Goldが300なら、箱にも300を写します。初期値0の箱をそのまま保存しないよう、この接続を確かめてください。
3. スロットへ書き出す
Set Saved Goldの後へ Save Game to Slot をつなぎます。
| 入力 | 設定・接続 |
|---|---|
| Save Game Object | SaveRefのGet |
| Slot Name | SlotNameのGet |
| User Index | 0 |

保存先の2入力は、次のようにつなぎます。同じSave Game to Slotの入力を分けて示した図なので、保存ノードをもう1個作る必要はありません。

User Indexは、保存するユーザーを区別する番号です。今回の1人用の実験では、保存・ロードとも0でそろえます。
最後に、Save Game to Slotの白い出力を Branch へつなぎ、「Return Value」をBranchの「Condition」へ渡します。ここで返るのは箱ではなく、書き込みに成功したかどうか です。
True側にPrint Textで セーブしました、False側に セーブに失敗しました と出します。両方とも画面・ログ出力を有効、Durationを10、KeyはNoneにしてください。

Save Game to Slot は、書き込みを終えてから次へ進む方式です。今回は整数1項目なので、この形で仕組みを確認します。ゲーム中に大きなデータを自動保存する場合の非同期版は、おまけで触れます。Save Game to Slotの公式API
ロード:読んだ値をゲー ムへ戻す
1. 同じスロットを読む
数字キー 3 の「Pressed」から Load Game from Slot をつなぎます。「Slot Name」へ同じSlotNameのGetを渡し、「User Index」は0にします。

保存先と読み込み先が違うと、期待した記録を取り出せません。両方に同じ変数SlotNameを使うのは、この食い違いを防ぐためです。
2. BP_DemoSaveとして中身を読む
Load Game from Slotの「Return Value」からドラッグし、Cast To BP_DemoSave を作ります。「Object」にReturn Valueを渡し、白い実行線もつなぎます。
Cast は、受け取ったものがBP_DemoSaveとして扱えるかを確かめる操作です。ロードの戻り値は共通のSave Game型なので、ここを通すことで、今回追加したSavedGoldを読めます。別の型のデータを、無理に作り替える処理ではありません。
「Cast Failed」にはPrint Textをつなぎ、セーブがないか、読み込めません と表示します。画面・ログ出力を有効、Durationを10、KeyはNoneです。

セーブがない初回や読み込みに失敗した場合、Load Game from SlotはNoneを返します。この場合もCastの失敗側へ進み、Goldは変更しません。ファイルを読めた場合だけ、ゲーム内の値を戻す ようにします。Load Game from Slotの公式API
3. SavedGoldをGoldへ戻す
Castの「As BP Demo Save」から Get Saved Gold を作り、その出力を Set Gold の値へつなぎます。白い実行線はCastの成功側からSet Gold、続けてShowGoldへつなぎます。

この図のCastは、前の手順で置いた同じノードです。保存前のSaveRefを読むのではなく、今ロードして返ってきた箱 から値を取り出します。
ここまでつないで、初めて画面の所持金が保存時の値へ戻ります。ロードノードが成功しただけで、Actorの変数が自動的に変わるわけではありません。
確認:値を変えて、Playもやり直す
コンパイルして保存し、次の順で確かめましょう。ゲーム画面をクリックしてからキーを押します。
| 操作 | 期待する結果 |
|---|---|
| 1を押す | 所持金が300になる |
| 2を押す | 「セーブしました」と表示される |
| 4を押す | 所持金が900になる |
| 3を押す | 保存した300へ戻る |

900へ変えた後は、2 を押さずに 3 を押します。そこで再び保存すると、スロットの内容も900へ更新されるためです。
次にPlayを停止し、再びPlayしてください。開始時は0になり、3を押すと300へ戻れば成功 です。Actorは作り直され、SaveRefもNoneへ戻っています。それでも値が戻ることで、ファイルへ残ったことを確認できます。
セーブがない場合も試す
Playを停止し、BP_SaveDemoのSlotNameの初期値を NotesSaveDemoEmpty など、まだ使っていない名前へ変えます。コンパイルしてPlayし、2 で保存する前に 3 を押してください。
セーブがないか、読み込めません と出て、Goldが0のままなら想定どおりです。確認後はSlotNameを NotesSaveDemo01 へ戻します。保存ファイルを削除せずに、初回起動と同じ状態を試せます。
| うまくいかないとき | 確認するところ |
|---|---|
| 1や4を押しても表示が変わらない | Actorを1個配置したか、Auto Receive Input=Player 0か、ゲーム画面にフォーカスがあるか |
| 保存できるが、ロードすると0になる | Set Saved GoldのTarget=SaveRef、値=Gold、書き込みより前の実行線 |
| 読み込めないメッセージが出る | SlotName・User Indexの一致、保存成功表示、Cast先がBP_DemoSaveか |
| ロード後も900のまま | Cast成功側→Set Gold、Get Saved Goldの値、ShowGoldの呼び出し |
| Playをやり直すと勝手に記録が0になる | BeginPlayへ保存処理をつないで、初期値で上書きしていないか |
おまけ:自分のゲームへ広げるとき
保存するのは、再開に必要な値
所持金の往復ができたら、HP・位置・持ち物なども同じ考え方で増やせます。Save Gameへ変数を追加するだけでなく、セーブ時に写す処理と、ロード後に戻す処理を両方追加 してください。
| 再開したいもの | 保存する値の例 | ロード後にすること |
|---|---|---|
| プレイヤーのHP | 現在HP | プレイヤーの変数へ戻す |
| 再開地点 | チェックポイントのIDや位置 | 対応する場所へプレイヤーを戻す |
| 持ち物 | アイテムIDと個数 | IDから種類を調べ、所持数を戻す |
Actorへの参照を保存しても、そのActorを生み出し直し、HPや持ち物まで丸ごと復元してくれるわけではありません。参照は「どの相手か」、保存したい値は「その相手がどんな状態か」 です。
たとえば武器なら、「どの種類か」を表すWeaponIDと、「あとどれだけ使えるか」を表す耐久値(Durability)を保存します。ロード後はIDに対応する武器を用意し、保存した耐久値へ戻します。

アイテムのIDから種類を調べるには、Data TableやData Assetの設定を使えます。種類の設定と、プレイヤーの所持数は分けて保存します。
位置を戻す場合は、移動中の速度なども整える必要があります。チェックポイントとリスポーンで、復帰する場所とタイミングを含めて扱います。
「つづきから」を表示したい
Does Save Game Exist で、指定したスロットがあるかを調べられます。「つづきから」ボタンを表示するか、押せる状態にするかの判断に使えます。
ただし、ファイルがあることと、正しく読み込めることは別です。実際のロードでは、今回のように失敗側の処理も残しておきます。Does Save Game Existの公式API
ゲーム中の自動保存は、非同期版を検討する
非同期 は、ディスクへの書き込みを待つ間も、ゲーム側の処理を進める方式です。Async Save Game to Slot は、このためのノードです。
使う場合は「Completed」の後で「Success」をBranchへ渡し、成功したときだけ保存完了を表示します。Completedは「処理が終わった」という意味で、失敗しても呼ばれます。保存が終わるまでは、同じスロットへの次の保存やロードを待たせます。非同期セーブの公式API
保存データをまとめる処理など、ゲーム側で行う仕事は残るため、非同期にすれば負荷がすべて消えるわけではありません。まず今回の小さな保存を動かし、保存項目や呼ぶタイミングに合わせて切り替えていきます。
保存先と、項目を増やすときのこと
開発中のPCでは、通常、プロジェクトの Saved/SaveGames/ に .sav ファイルができます。今回の例なら NotesSaveDemo01.sav です。パッケージ化したゲームや別のプラットフォームでは保存場所が異なります。
ゲームの更新で保存項目を変えるなら、古い記録をどう読み替えるかも必要です。バージョン番号を付けるだけで自動解決するわけではないので、セーブデータのバージョン管理で移行の考え方を確認してください。
ゲームを閉じた後まで残す必要がなく、レベル間だけで値を持ち越したいなら、Game Instanceも使えます。残したい期間によって、値の置き場所を選びましょう。
まとめ
- SaveGameオブジェクトを作っただけでは、ファイルに残らない
- 保存も読み込みも、成功したかを必ず確かめる
- 読めなかったときに何を使うかを決めておく
保存する前の問いかけは、「これは次回の起動 にも要るか」 です。今回のプレイ中だけなら GameInstance で足ります。
項目を足したあとの互換は セーブデータの移行 で扱います。