🐙

UnityのTips!PlayerPrefsでセーブデータを管理する方法 : ローカルランキングの実装

2024/12/07に公開

はじめに

ゲーム開発において、データの保存と読み込みは非常に重要なスキルです。Unityでは簡単にデータを保存できる仕組みとしてPlayerPrefsが用意されています。本記事では、PlayerPrefsの基本的な使い方から、注意点や応用例までを解説します。

Unityの基本操作からC#スクリプトの基礎まで、やさしく学べる入門チュートリアルはこちら
https://zenn.dev/ryuryu_game/books/fd28de9d8e963a/viewer/0570af

1. PlayerPrefsとは?

PlayerPrefsは、Unityが提供するキーと値の形式でデータを保存する仕組みです。
主に以下のような軽量データの保存に使用されます:

  • ゲーム設定(音量、解像度など)
  • スコアやプレイヤー名
  • その他、ゲーム進行状況の簡単な保存

PlayerPrefsはプラットフォームに依存せず、どの環境でも同じコードで使用できます。

2. PlayerPrefsの基本操作

データの保存

PlayerPrefsには、以下のデータ型を保存できます:

  • int(整数)
  • float(小数)
  • string(文字列)

それぞれの保存方法は以下の通りです。

using UnityEngine;

public class PlayerPrefsExample : MonoBehaviour
{
    void Start()
    {
        // 整数を保存
        PlayerPrefs.SetInt("HighScore", 100);

        // 小数を保存
        PlayerPrefs.SetFloat("Volume", 0.75f);

        // 文字列を保存
        PlayerPrefs.SetString("PlayerName", "UnityMaster");

        // 保存を確定
        PlayerPrefs.Save();

        Debug.Log("データが保存されました!");
    }
}

データの読み込み

保存したデータは、以下の方法で読み込むことができます。

void LoadData()
{
    // 整数を読み込み(デフォルト値を指定)
    int highScore = PlayerPrefs.GetInt("HighScore", 0);

    // 小数を読み込み
    float volume = PlayerPrefs.GetFloat("Volume", 1.0f);

    // 文字列を読み込み
    string playerName = PlayerPrefs.GetString("PlayerName", "Guest");

    Debug.Log($"HighScore: {highScore}, Volume: {volume}, PlayerName: {playerName}");
}

データの削除

保存されたデータを削除する方法は以下の通りです。

// 特定のキーを削除
PlayerPrefs.DeleteKey("HighScore");
// 全てのキーを削除
PlayerPrefs.DeleteAll();

3. ローカルランキングに応用する

3-1. なぜローカルランキングが有効なのか?

大規模なオンラインサーバーを用意する余裕がない場合でも、ローカル環境だけで「自分vs自分」の継続プレイを促すことができます。たとえば、連射シューティングやタイムアタック系のゲームでは、過去の自分の記録を更新する楽しみを持たせるだけでも十分に熱中度が高まるものです。

3-2. ローカルランキング例:上位5件を保存する

PlayerPrefsはキー名が文字列なので、「Score0」「Score1」「Score2」…といった形で複数スコアを保持できます。以下、シンプルなサンプルです。

LocalRankingManager
using UnityEngine;

public class LocalRankingManager : MonoBehaviour
{
    private const int RANKING_COUNT = 5;

    public void SaveScore(int newScore)
    {
        // 既存スコアを読み込み
        int[] scores = new int[RANKING_COUNT];
        for(int i = 0; i < RANKING_COUNT; i++)
        {
            scores[i] = PlayerPrefs.GetInt("Score" + i, 0);
        }

        // 新スコアを挿入してソート(上位5件)
        // 例:単純挿入→ソート→上位5件を上書き
        System.Array.Resize(ref scores, RANKING_COUNT + 1);
        scores[RANKING_COUNT] = newScore;
        System.Array.Sort(scores);
        System.Array.Reverse(scores);

        // 上位5件を保存
        for(int i = 0; i < RANKING_COUNT; i++)
        {
            PlayerPrefs.SetInt("Score" + i, scores[i]);
        }
        PlayerPrefs.Save();

        Debug.Log("ローカルランキングを更新しました");
    }

    public int[] LoadScores()
    {
        int[] loaded = new int[RANKING_COUNT];
        for(int i = 0; i < RANKING_COUNT; i++)
        {
            loaded[i] = PlayerPrefs.GetInt("Score" + i, 0);
        }
        return loaded;
    }
}
  • SaveScoreメソッドで既存スコアを読み込み、新スコアを混ぜて並び替え
  • 上位5件だけを再度PlayerPrefsに書き戻す
  • LoadScoresで取り出してUIに表示すれば、ローカルランキングの完成

3-3. 書き込み頻度に要注意

シューティングゲームなどでフレームごとにScoreを更新するような場面では、毎フレームSetIntするとパフォーマンスを圧迫します。更新はゲーム終了時やステージクリア時など、タイミングをまとめるのがおすすめです。

4. PlayerPrefsの注意点

1. 大量のデータ保存には不向き

PlayerPrefsは軽量データ用に設計されています。大量のデータ(例えば、ゲームのセーブデータ全体など)は、ファイルやデータベースを使用するのが適切です。

2. データは暗号化されない

保存されるデータは平文のため、プレイヤーが直接編集可能です。機密性の高いデータには暗号化を適用するか、別の保存手段を検討してください。

3. 書き込み場所の違い

保存先のディレクトリはプラットフォームによって異なります。

例えば:
• Windows: レジストリ
• macOS: ~/Library/Preferences/
• iOS/Android: アプリデータフォルダ

4. PlayerPrefsの応用例

音量設定を保存する

ゲームの音量をPlayerPrefsで保存し、次回の起動時に再現する例です。

using UnityEngine;

public class VolumeManager : MonoBehaviour
{
    private const string VolumeKey = "Volume";

    void Start()
    {
        // デフォルト値を読み込む
        float volume = PlayerPrefs.GetFloat(VolumeKey, 0.5f);
        AudioListener.volume = volume;
        Debug.Log($"音量をロード: {volume}");
    }

    public void SetVolume(float volume)
    {
        // 音量を保存
        PlayerPrefs.SetFloat(VolumeKey, volume);
        PlayerPrefs.Save();
        Debug.Log($"音量を保存: {volume}");
    }
}

ハイスコアの管理

ハイスコアをPlayerPrefsで管理し、ゲーム中に更新する例です。

using UnityEngine;

public class HighScoreManager : MonoBehaviour
{
    private const string HighScoreKey = "HighScore";

    public void CheckAndUpdateHighScore(int currentScore)
    {
        int highScore = PlayerPrefs.GetInt(HighScoreKey, 0);

        if (currentScore > highScore)
        {
            PlayerPrefs.SetInt(HighScoreKey, currentScore);
            PlayerPrefs.Save();
            Debug.Log($"ハイスコア更新!新しいスコア: {currentScore}");
        }
        else
        {
            Debug.Log($"ハイスコア維持: {highScore}");
        }
    }
}

5. まとめ

PlayerPrefsは、簡単なデータ保存と読み込みに非常に便利な機能です。以下のポイントを意識して使いましょう!

  • 軽量データ(設定値や小規模な進行データ)の保存に適している
  • 暗号化されていないため、機密性のあるデータには向かない
  • 大量のデータには他の保存方法を検討する

PlayerPrefsを活用して、効率的なゲーム開発を実現しましょう!

https://zenn.dev/ryuryu_game/articles/2ff2c49909a3de

この記事を読んでもっと実践したいと感じたあなたへ

Unity開発を効率よく進めるためには、実践的なスキルと仲間との交流が欠かせません。
そんな方におすすめのステップが、下記の3つです。

1. 有料教材「どこでもUnity教室」でゲーム制作を短期マスター

  • 5日でシンプルなFPS完成:初心者向けに要点を押さえたカリキュラム
  • C#や最新のInputSystem、FPS実装まで網羅:つまずきやすいポイントを先回りで解説
  • 購入特典:Discord招待+サンプルプロジェクトDLで、疑問や実装例を即確認

Unity初心者でも最短5日で3D FPSが完成!今すぐ始める入門チュートリアルはこちら

https://zenn.dev/ryuryu_game/books/fd28de9d8e963a/viewer/0570af

2. 無料コミュニティで、疑問をすぐに解消&モチベーションUP

  • 初心者~中級者までOK:学習進度に合わせて質問や情報共有
  • 質問サポートが充実:わからないことを仲間や講師に即相談
  • 学習仲間と切磋琢磨:一緒に学ぶから続けやすい

Discordサーバー参加はこちら

https://discord.gg/5FwuKCacNy

3. 実績豊富な“ゲーム開発所RYURYU”があなたをトータルサポート

  • コナラ総販売200件超:さまざまなUnity開発の依頼を対応
  • VR/AR/AIなど最新技術にも精通:幅広いノウハウを活かして開発支援
  • ゲームクリエイター甲子園や東京ゲームショウなど出展実績多数

ご相談・お問い合わせはこちら

https://coconala.com/users/1772507

Discussion