【Unity】Unityで簡単データセーブ!PlayerPrefsの使い方と注意点

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

ゲームの音量設定やハイスコアなど、簡単なデータを保存するための機能「PlayerPrefs」。その基本的な使い方であるSetInt, GetIntや、使うべきでないケース、そして暗号化の必要性について解説します。

せっかく調整してもらった音量設定が、ゲームを再起動したら元どおり——データを保存しないゲームは、起動するたびに「初対面」に戻ってしまいます。音量・画質・ハイスコアといった小さなデータをいちばん手軽に保存できるのが、Unity標準の PlayerPrefs です。

この記事では、PlayerPrefsの基本的な使い方(Set/Get/Save)と、その手軽さの裏にある注意点・使ってはいけないケース、そして実際のオプション画面への組み込みまでを解説します。

PlayerPrefsのイメージ。粘土の小さな引き出し棚に、音量つまみ・ハイスコアのメダル・画質の歯車がキー付きの引き出しへ仕舞われている

この記事でわかること

  • PlayerPrefsの基本——キーと値のペアで保存する仕組み
  • Set/Getメソッドと デフォルト値の鉄則
  • Save()を呼ぶタイミング(クラッシュ対策)
  • 使ってはいけないケース——暗号化されない・3型しか扱えない
  • 設定はPlayerPrefs、セーブデータはJSONファイル、の使い分け

Sponsored

PlayerPrefsの基本的な使い方

PlayerPrefsは、3種類のデータ型(int, float, string)のみをサポートしています。それぞれのデータ型に対応したSetメソッド(保存)とGetメソッド(読み込み)が用意されています。

キーと値の引き出しの図。MasterVolumeと書かれた引き出しに0.8、HighScoreの引き出しに1200、PlayerNameの引き出しに名前カードが入っており、キーの名前で出し入れする仕組みを表す

データの保存: Setメソッド

データを保存するには、SetInt(), SetFloat(), SetString()メソッドを使います。第一引数にデータを識別するためのキー(文字列)、第二引数に保存したい値を指定します。

using UnityEngine;

public class GameSettings : MonoBehaviour
{
    public void SaveVolume(float volumeLevel)
    {
        // "MasterVolume"というキーで、float型の音量データを保存
        PlayerPrefs.SetFloat("MasterVolume", volumeLevel);
    }

    public void SaveHighScore(int score)
    {
        // "HighScore"というキーで、int型のハイスコアを保存
        PlayerPrefs.SetInt("HighScore", score);
    }
}

重要: Setメソッドを呼び出しただけでは、データはまだメモリ上にあり、ディスクには書き込まれていません。ゲームがクラッシュした場合などにデータが失われるのを防ぐため、重要なデータを保存した直後にはPlayerPrefs.Save()を呼び出して、明示的にディスクへの書き込みを指示するのが安全です。

public void SaveAllSettings()
{
    PlayerPrefs.SetInt("QualityLevel", 2);
    PlayerPrefs.SetFloat("MusicVolume", 0.8f);

    // メモリ上の変更をディスクに即座に書き込む
    PlayerPrefs.Save();
}
SetとSaveの関係図。Setはメモリに書くだけでクラッシュで消える可能性があり、Save()を呼ぶとディスクに書き込まれて電源を切っても残る
Sponsored

データの読み込み: Getメソッド

保存したデータを読み込むには、GetInt(), GetFloat(), GetString()メソッドを使います。第一引数に、保存時に使ったキーを指定します。

このとき、第二引数としてデフォルト値を指定することが非常に重要です。指定したキーのデータが存在しない場合(例: ゲームの初回起動時)、このデフォルト値が返されます。デフォルト値を指定しないと、キーが存在しない場合に0や空文字が返され、意図しない挙動の原因となります。

デフォルト値の仕組み。キーがあれば保存された1200が返り、キーがない初回起動時はGetIntの第二引数に指定したデフォルト値0が返る
using UnityEngine;
using UnityEngine.UI;
using TMPro;   // テキスト表示はTextMeshProが現在の標準

public class LoadSettings : MonoBehaviour
{
    public Slider volumeSlider;
    public TextMeshProUGUI highScoreText;

    void Start()
    {
        // "MasterVolume"キーのデータを読み込む。存在しない場合はデフォルト値1.0fを使う。
        float savedVolume = PlayerPrefs.GetFloat("MasterVolume", 1.0f);
        volumeSlider.value = savedVolume;

        // "HighScore"キーのデータを読み込む。存在しない場合はデフォルト値0を使う。
        int highScore = PlayerPrefs.GetInt("HighScore", 0);
        highScoreText.text = "High Score: " + highScore;
    }
}

tips: テキスト表示に旧TextではなくTextMeshProUGUIを使う理由は TextMeshProの記事 を参照してください。

その他の便利なメソッド

  • PlayerPrefs.HasKey(string key): 指定したキーのデータが存在するかどうかをbool値で返します。初回起動時の処理を分岐させたい場合などに便利です。
  • PlayerPrefs.DeleteKey(string key): 指定したキーのデータを削除します。
  • PlayerPrefs.DeleteAll(): すべてのPlayerPrefsデータを削除します。ゲームのリセット機能などで使いますが、非常に強力なため取り扱いには注意が必要です。

PlayerPrefsの注意点と限界

PlayerPrefsは非常に手軽で便利ですが、万能ではありません。使うべきでないケースを理解しておくことが重要です。

1. セキュリティの問題

PlayerPrefsで保存されるデータは、暗号化されていません。少し知識のあるユーザーであれば、保存されたファイルを簡単に見つけ出し、内容を書き換えることができてしまいます。ハイスコアや所持金といった、改ざんされると困るような重要なデータをPlayerPrefsでそのまま保存するのは非常に危険です。

PlayerPrefs�の改ざんリスクの図。保存されたHighScoreは平文のまま見えてしまい、ユーザーが999999に簡単に書き換えられる。大事なデータをそのまま入れないこと

対策:

  • 重要なデータを保存する場合は、PlayerPrefsを使う前に必ず独自の暗号化処理を施す必要があります。
  • あるいは、PlayerPrefsは使わずに、JSONやバイナリ形式でファイルに書き出し、そのファイル自体を暗号化する、より本格的なセーブシステムの導入を検討します。

2. 複雑なデータの保存

PlayerPrefsが扱えるのはint, float, stringの3種類のみです。プレイヤーのインベントリ(アイテムのリスト)、キャラクターのステータス、クエストの進捗といった複雑な構造を持つデータを保存するには不向きです。

対策:

  • JsonUtilityJson.NETといったライブラリを使って、自作クラスのインスタンスをJSON形式の文字列に変換(シリアライズ)し、それをPlayerPrefs.SetString()で保存する方法があります。これは比較的手軽で一般的な手法です。
  • より大規模で複雑なセーブデータの場合は、専用のセーブファイル(バイナリ形式など)を作成する方が、パフォーマンスや拡張性の面で優れています。

実践:音量設定を保存するオプション画面を組む

アクションでもRPGでもパズルでも、リリースするゲームには必ず「オプション画面の音量スライダー」が付きます。そして仕様は毎回同じ——動かしたら即反映、閉じたら保存、次回起動時に復元。PlayerPrefsのもっとも王道な使い道を、実際に組んでみましょう。

音量設定の保存フロー。スライダーを動かし、閉じるときにSetFloatとSaveで保存すると、次回起動でも同じ位置に復元される

uGUIのSliderUIの基本 参照)に、次のスクリプトをつなぎます。

using UnityEngine;
using UnityEngine.UI;

public class VolumeSettings : MonoBehaviour
{
    private const string VolumeKey = "MasterVolume";   // キー名は定数化(タイプミス事故防止)

    [SerializeField] private Slider volumeSlider;

    void Start()
    {
        // 起動時: 保存された音量を復元(初回はデフォルト値1.0)
        float saved = PlayerPrefs.GetFloat(VolumeKey, 1.0f);
        volumeSlider.value = saved;
        AudioListener.volume = saved;

        // スライダーを動かしたら即・音に反映(保存はまだしない)
        volumeSlider.onValueChanged.AddListener(v => AudioListener.volume = v);
    }

    // オプション画面を閉じるボタンから呼ぶ
    public void SaveAndClose()
    {
        PlayerPrefs.SetFloat(VolumeKey, volumeSlider.value);
        PlayerPrefs.Save();   // 閉じるタイミングでまとめてディスクへ
        gameObject.SetActive(false);
    }
}

ポイントは2つです。

  • 反映は毎フレームでも、保存は「閉じるとき」だけ: スライダーを動かすたびにSave()を呼ぶとディスク書き込みが頻発します。音への反映(AudioListener.volume)は即時、ディスクへの保存は画面を閉じる1回だけ、と分けるのが定番です。
  • 復元とデフォルト値はセット: Start()での復元時にGetFloat(key, 1.0f)とデフォルト値を渡しておけば、初回起動でも「音量最大」から自然に始まります。

BGMとSEを別々のスライダーにするなら、キーを"BGMVolume"/"SEVolume"に分けて同じ形を繰り返すだけです。ミキサー(Audio Mixer)での本格的な音量制御は オーディオ入門の記事 で解説しています。

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

  • boolの保存イディオム: bool型は直接保存できないため、PlayerPrefs.SetInt("IsTutorialDone", isDone ? 1 : 0)GetInt("IsTutorialDone", 0) == 1のようにintの0/1に変換するのが定番です。
  • キー名は定数化する: "MasterVolume"のような文字列キーをそのまま各所に書くとタイプミスが事故になります。public static class PrefsKeys { public const string MasterVolume = "MasterVolume"; }のように1箇所にまとめるのがおすすめです。
  • 保存場所の実際: Windowsではレジストリ(HKCU\Software\[会社名]\[製品名])、macOS/iOSではplist、AndroidではSharedPreferencesに保存されます。「ファイルが見つからない」のはレジストリだからです。
  • エディタと実機は別: エディタでのPlayerPrefsはビルドした実機とは別の場所に保存されます。「エディタで保存したデータが実機にない」のは正常な挙動です。

まとめ

PlayerPrefsは、Unityにおけるデータ永続化の入門として最適なツールです。

  • int, float, string の3つの型を、キーと値のペアで簡単に保存できる。
  • Setメソッドで保存し、Getメソッドで読み込む。重要な保存の後はSave()
  • Getメソッドでは、データが存在しない場合に備えてデフォルト値を指定するのが鉄則。
  • データは暗号化されないため、ハイスコアなどの改ざんされたくないデータの保存には向かない。
  • 複雑なデータ構造の保存には、JSONへのシリアライズなどを組み合わせる工夫が必要。

PlayerPrefsの長所と短所を正しく理解し、音量設定のような単純なオプションにはPlayerPrefsを、セーブデータのような複雑で重要な情報にはより堅牢なファイルベースのシステムを、というように適切に使い分けることが重要です。本格的なセーブシステムの作り方は JSONセーブの記事 で解説しています。