【Unreal Engine】Save Gameでセーブ・ロードを実装する方法

作成: 2026-02-07最終更新: 2026-07-20

UEのSave Gameによるセーブ・ロードをBlueprintで実装する手順を図解。箱を作る・詰める・開けるの3手順、チェックポイント復帰の実践、Actor参照を保存してはいけない理由、非同期セーブまで。

チェックポイントまで進んで、装備を整えて、所持金を貯める。そこでPlayを止めると、すべてが消えます。次に起動したときには、また最初からです。

これを解決するのが Save Game です。ゲームの状態をファイルへ書き出し、次回の起動時に読み戻す仕組みで、Blueprintだけで実装できます。この記事では、Save Gameクラスの作り方から、チェックポイントでセーブしてリスポーンで復帰する実践、そして初心者が必ずはまる「Actorの参照は保存できない」という落とし穴までを解説します。

ゲーム画面の状態を箱に詰めて、棚のスロットへ収める。Save Gameのイメージ

この記事でわかること

  • Save Gameの正体= 持ち出し用の箱 。3手順は 作る・詰める・開ける
  • Blueprintでのセーブとロードの 完成ノードグラフ
  • 実践: チェックポイントで保存し、死んだら復帰する
  • Actor参照を保存してはいけない 理由と、代わりに保存するもの
  • ゲーム中のセーブは 非同期

Sponsored

Save Gameとは:持ち出し用の箱

ゲーム実行中の値は、すべてメモリの上にあります。プレイヤーのHPも、所持金も、電源を切れば消えます。ファイルとして残すには、 残したい値だけを別の入れ物に移してから書き出す 必要があります。この入れ物が Save Game です。

3つの手順に分かれます。

手順すること使うノード
作る何を保存するかを決めた「型」を用意する(Blueprint Classを作成)
詰める現在の値を箱にコピーして、スロットへ書き出すCreate Save Game Object / Save Game to Slot
開けるスロットから箱を取り出し、値をゲームへ戻すLoad Game from Slot
ゲーム内の値を箱へ移し、箱をスロットへ書き出す。ロードはその逆をたどる

スロット はセーブファイルの名前です。"SaveSlot01" のような文字列を指定すると、その名前でファイルが作られます。名前を変えれば、セーブデータを複数持てます。

Sponsored

手順1:箱の型を作る

コンテンツブラウザで右クリックし、 Blueprint Class を選びます。親クラスの選択ダイアログで 「All Classes」の検索欄に SaveGame と入力し、SaveGame を選択してください。よく使うクラスのボタンには並んでいないので、検索から選びます。

名前は BP_SaveGame としておきます。開いたら、保存したい値を変数として追加します。

変数名用途
SavedHealthFloatHP
SavedGoldInteger所持金
SavedLocationVectorプレイヤーの座標
SavedItemIDsName(配列)所持アイテムのID

このBlueprintには ロジックを書きません 。値を並べておくだけの入れ物として使います。

補足: 保存する変数は最小限にしてください。ロード時に計算し直せる値(最大HP、アイテムの表示名、装備による攻撃力の合計など)は保存しなくて構いません。保存する項目が増えるほど、後でセーブデータの互換性を保つのが大変になります。

手順2:詰めて保存する

セーブ処理は「箱を用意する」「値を移す」「書き出す」の順です。

Create Save Game Objectで箱を作り、変数を順に設定し、Save Game to Slotで書き出すBlueprintノードグラフ
BP_PlayerCharacter(またはGameInstance)
Custom Event: SaveGame
  → Create Save Game Object(Save Game Class: BP_SaveGame)
      Return Value → Promote to variable(名前: SaveRef)
  → Set Saved Health(Target: SaveRef, Value: CurrentHealth)
  → Set Saved Gold(Target: SaveRef, Value: Gold)
  → Set Saved Location(Target: SaveRef, Value: GetActorLocation)
  → Save Game to Slot(Save Game Object: SaveRef, Slot Name: "SaveSlot01", User Index: 0)

Create Save Game ObjectSave Game Class ピンで、作った BP_SaveGame を選ぶのを忘れないでください。ここが空だと箱ができません。

Save Game to Slot は成功したかどうかを bool で返します。この戻り値を Branch に繋いでおくと、書き込みに失敗したときに気づけます。

注意: Save Game to Slot は書き込みが終わるまで処理を止めます。数値だけの小さなセーブなら一瞬ですが、ゲームプレイ中に呼ぶと一瞬引っかかることがあります。対処はおまけで扱います。

手順3:開けて戻す

ロードは逆順です。ただし、 2つの手続きが要ります

Does Save Game Existで存在確認し、Load Game from Slotの戻り値をCast To BP_SaveGameしてから値を読み出すBlueprintノードグラフ
Custom Event: LoadGame
  → Does Save Game Exist(Slot Name: "SaveSlot01", User Index: 0)
      → Branch
          True →
            Load Game from Slot(Slot Name: "SaveSlot01", User Index: 0)
              Return Value → Cast To BP_SaveGame
                As BP Save Game →
                  Set Current Health(Value: Saved Health)
                  → Set Gold(Value: Saved Gold)
                  → Set Actor Location(New Location: Saved Location)
          False →
            Print String("セーブデータがありません")

1つ目が Does Save Game Exist による存在確認 です。初回起動時にはセーブファイルがないので、これがないと「なぜか何も起きない」状態になります。

厳密にはこの確認は必須ではありません。Load Game from Slot は失敗すると None を返すので、Is Valid で受けても同じことができます。ただし、 ファイルはあるのに壊れている・型が違う というケースもあるため、次のCastの失敗側も塞いでおくのが確実です。

2つ目が Cast To BP_SaveGame です。Load Game from Slot が返すのは基底の Save Game 型で、そのままでは SavedHealth などの変数が見えません。Castを挟んで自分のクラスに変換すると、変数が読めるようになります(→ Castの記事)。

「セーブはできているのにロードで値が取れない」の原因は、ほぼこのCast忘れです。

Sponsored

実践:チェックポイントで保存し、復帰する

ここまでの部品で、実際に使える仕組みを組みます。アクションゲームのチェックポイント、ローグライクの階層セーブ、オープンワールドの拠点セーブ。「ある地点を通過したら記録し、死んだらそこへ戻す」構図は、どのジャンルでも同じです。

完成形

チェックポイントに触れると保存され、その後で落下死しても、 触れた時点のHP・所持金・位置から再開 します。

チェックポイントに触れて保存、落下死、リスポーンで保存地点の状態に戻る一連の流れ

再現条件

BP_SaveGame に、手順1の変数のうち3つを用意します。

変数初期値
SavedHealthFloat100.0
SavedGoldInteger0
SavedLocationVector(0, 0, 0)

BP_ThirdPersonCharacter には次を用意します。

変数初期値
CurrentHealthFloat100.0
GoldInteger0
IsDeadBooleanfalse

さらに BP_Checkpoint(親は Actor)を作り、Box Collisionコンポーネントを追加します。詳細パネルで Generate Overlap Events がオン 、Collision Presetが OverlapAllDynamic(Pawnに反応する設定)になっていることを確認してください。ここが既定のままだと、触れてもイベントが飛びません。

加えて、動かすための下ごしらえが3つ要ります。

用意するもの内容
GameModeの設定Default Pawn ClassBP_ThirdPersonCharacter になっていること
レベルへの配置BP_Checkpoint を1つ配置する
所持金を増やす手段動作確認用に、キー入力(1 キーなど)で Gold に +100 するイベントを仮に付けておく

チェックポイント側

BP_Checkpoint のBox Collisionで On Component Begin Overlap を取り、触れたのがプレイヤーなら、プレイヤー側のセーブ処理を呼びます。

BP_Checkpoint
On Component Begin Overlap(Box)
  → Cast To BP_ThirdPersonCharacter(Object: Other Actor)
      As BP Third Person Character →
        Save Game(プレイヤーのCustom Eventを呼ぶ)
        → Print String("チェックポイント記録")

プレイヤー側

手順2・手順3で作ったセーブ/ロードのイベントをそのまま使います。位置の保存は GetActorLocation を、復帰時は SetActorLocation を使います。

次に「死んだとき」を作ります。ここが最初のつまずきどころで、 UEの標準のKill Zに任せてはいけません 。Kill Zに落ちたCharacterは破棄されるので、そのCharacterに書いた復帰処理は動かないためです。

代わりに、落下を自前で判定します。BP_ThirdPersonCharacter のTickか、床下に置いたBox Collision(OnActorBeginOverlap)から OnDeath を呼びます。

BP_ThirdPersonCharacter
Event Tick
  → Get Actor Location → Break Vector(Z)
  → Z < -500 かつ IsDead == false
      → Branch True → Set IsDead(true)→ OnDeath

復帰処理では、ロードの前に 落下速度をリセット してください。SetActorLocation で座標だけ戻しても、落下中の速度が残っていると、戻った直後にまた落ちていきます。

Custom Event: OnDeath
  → Stop Movement Immediately(Target: Character Movement)
  → Load Game(手順3のCustom Event)
  → Set IsDead(false)

Stop Movement Immediately のTargetには Character Movement コンポーネントを繋ぎます。

補足: この作りは、Characterを作り直す「リスポーン」ではなく、 同じCharacterを保存地点へ戻して状態を復元する ものです。個人開発ではこちらのほうが扱いやすく、UIやカメラの参照も切れません。

確認する

1 キーで所持金を300まで増やし、チェックポイントに触れてから、床の端から落ちてください。 位置がチェックポイントに戻り、所持金が300のままであれば成功 です。

  • 所持金が0に戻る → セーブ時の Set Saved Gold の接続漏れ、またはロード時のCast忘れ
  • 位置は戻るが落下し続けるStop Movement Immediately が抜けている
  • 落ちても何も起きないOnDeath が呼ばれていない。Kill Zに任せていないか、Z座標のしきい値を確認
  • チェックポイントに触れても反応しない → Box Collisionの Generate Overlap Events かCollision Presetの設定

もう1つ、 PIEを停止してから再度Playし、ロードだけを実行 してみてください。ここで前回の値が戻れば、メモリ上ではなく ファイルに残っている ことの確認になります。同一Play中のテストだけでは、ここまでは確かめられません。

ポイントは2つです。

  • セーブは「今の値を箱へ写す」だけ: チェックポイントは合図を送る役に徹し、何を保存するかはプレイヤー側が決めます。この分担にしておくと、保存項目が増えてもチェックポイント側を触らずに済みます
  • 復帰は座標だけでは足りない: 速度、入力の状態、再生中のアニメーション。位置を戻したあとに残っている「動きの続き」を止める処理が要ります。ここを忘れると「戻ったのにまた死ぬ」という挙動になります

セーブする項目が10個を超えてきたら、Structでまとめると、ノードの数を増やさずに項目を増やせます。

Sponsored

保存してはいけないもの

Save Gameの変数には、Actor参照やコンポーネント参照も 入れられてしまいます 。エラーも出ません。しかし、これを当てにした設計は壊れます。

左:Actor参照を保存してもロード時には空になる。右:IDや座標という値なら復元できる

参照が指しているのは「そのオブジェクトそのもの」であって、中身のデータではありません。レベルに最初から配置してあるActorのように条件が揃えば復元されることもありますが、 実行中に生成したActorは復元されず 、参照先が持っていたHPなどの状態も一緒には保存されません。「動くこともあるが、当てにできない」というのが実態です。

保存しない代わりに保存する
装備中の武器Actorへの参照武器のID(NameInteger
インベントリ内のアイテムObjectアイテムIDの配列
現在いる部屋のActor参照部屋の名前、またはプレイヤーの座標
Widgetへの参照開いていた画面を表すEnum

そのため 値だけを保存し、ロード時にそこから作り直す のが基本方針になります。武器IDから実物を復元するには、IDと実体を対応づける表が要るので、Data TableData Assetと組み合わせます。

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

アップデートで保存する項目が増える日に備える。 SaveGameクラスに変数を足すこと自体は安全ですが、 名前や型を変えると古いセーブの値が失われますSaveVersion を1つ持っておくだけで対処できるので、セーブを作る今のうちに入れておくのが得です(→ セーブデータのバージョン管理)。

  • ゲーム中のセーブは非同期で: Save Game to Slot の代わりに Async Save Game to Slot を使うと、ディスクへの書き込みが裏で進むため、引っかかりを軽くできます。ただし 完全に止まらなくなるわけではありません 。値を並べ直す処理はゲームスレッドで走るので、保存項目が多いと影響は残ります。完了時には Completed ピンが呼ばれますが、 これは成功・失敗のどちらでも呼ばれますSuccessBranch に通し、Trueのときだけ「セーブしました」を出してください
  • セーブデータの置き場所: エディタ実行時は プロジェクトフォルダ/Saved/SaveGames/SaveSlot01.sav 、パッケージ後のWindowsでは %LOCALAPPDATA%/プロジェクト名/Saved/SaveGames/ です(保存先はプラットフォームごとに違います)。動作確認のときは、このファイルを削除すれば「初回起動」の状態を再現できます
  • どこからセーブを呼ぶか: プレイヤーに書いた処理そのものは消えませんが、 レベルを移動するとCharacterが作り直されるため、変数に入れていた値は失われます 。ファイルに書き出すほどではない「レベル間だけの持ち越し」なら、Game Instanceに置くだけでゲーム中は消えません(仕組みの解説はSubsystem/GameInstanceにもあります)
  • 後から項目を増やすとき: BP_SaveGame に変数を追加しても、古いセーブデータは読み込めます(増えた変数は初期値になります)。ただし変数名を 変更・削除 すると、その値は失われます。名前は最初に決め切るつもりで付けてください
  • セーブデータは書き換えられる: .sav はプレイヤーが触れる場所にある普通のファイルです。オフラインの個人開発ゲームであれば、まずは気にしなくて構いません
// C++で型を定義する場合
UCLASS()
class MYPROJECT_API UMySaveGame : public USaveGame
{
    GENERATED_BODY()

public:
    UPROPERTY()
    float SavedHealth = 100.0f;

    UPROPERTY()
    int32 SavedGold = 0;

    UPROPERTY()
    FVector SavedLocation = FVector::ZeroVector;
};

保存・読み込みは UGameplayStatics::SaveGameToSlot / LoadGameFromSlot、非同期版は AsyncSaveGameToSlot / AsyncLoadGameFromSlot を使います。 UPROPERTY() を付け忘れた変数は保存されません 。ここがC++で最も多いつまずきです。

なお UPROPERTY() だけで保存されます(SaveGame 指定子は不要です)。この変数をBlueprintからも読み書きするなら、BlueprintReadWrite を追加してください。

まとめ

  • Save Gameは 持ち出し用の箱 。3手順は 作る(クラス)・詰める(Save to Slot)・開ける(Load from Slot)
  • ロードには Does Save Game Exist による存在確認Cast To による型変換 が要る。値が取れない原因はほぼCast忘れ
  • Actorやオブジェクトへの参照は当てにしない 。IDや座標という値で保存し、ロード時に再構築する
  • 復帰処理では 位置だけでなく速度も戻す 。忘れると戻った直後にまた落ちる
  • ゲームプレイ中のセーブは Async Save Game to Slot で引っかかりを減らす。Completed は失敗時も呼ばれるので Success で分岐する

あなたのゲームで、プレイヤーが「ここまでの進みが消えたら嫌だ」と思うのはどの瞬間でしょうか。そこが最初のチェックポイントの置き場所です。