persistentDataPath で指定された Unity 推奨のフォルダパスにデータを書き込む

ページ更新日 :
ページ作成日 :

検証環境

Windows
  • Windows 11
Unity エディター
  • 2021.3.3f1
入力システムパッケージ
  • 1.3.0

この Tips の前提設定

この Tips の説明の前提として以下の設定を事前に行っています。

はじめに

前回の Tips では PlayerPrefs を使用した方法でデータの保存や読み込みを行いました。 しかしこちらは巨大なデータの扱いやデータ共有の視点で見た場合の用途としては不向きな面があります。

今回はローカルのフォルダ・ディレクトリに対してデータの保存や読み込みを行います。 書き込む場所は基本的に自由に指定できますが、Unity で指定されている persistentDataPath を利用したほうがメリットはあるで今回はこちらを使用します。

UI の配置と処理

ここについては前回の Tips「PlayerPrefs を使用してデータを読み書きする」をそのまま流用しますので、 そちらを参考にしてボタンの処理が実行できるようになるところまで実装してください。

ついでに今回使用する persistentDataPath の値を表示する場所も配置しておきます。

どこがファイルの保存対象のフォルダパスであるかを確認する

今回使用するデータの保存先のフォルダパスは Application.persistentDataPath で取得できます。まずはその場所がどこであるかを表示してみます。

Start メソッドを作成してテキストフィールドに値を表示させてみます。

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ButtonEvent : MonoBehaviour
{
  // 省略

  /// <summary>パステキスト。</summary>
  [SerializeField] Text TextPath;


  /// <summary>最初に一度だけ呼ばれます。</summary>
  private void Start()
  {
    TextPath.text = Application.persistentDataPath;
  }

  // 省略
}

実行すると下側にパスが表示されるはずです。

今回 Windows で実行しているのでパスはこのようになります。 パスの中身は実行しているユーザーやプロジェクト設定の「CompanyName」や「ProductName」で変わることがあるので注意してください。 ゲームを作る際「CompanyName」や「ProductName」はゲーム公開前に決めておいて後々変更することがないようにしてください。

このパスは実行しているプラットフォームによって変わります。以下は公式サイトで記載されているパスになります。 Unity のバージョンによって変わる可能性もありますので、実際に実行して確認するようにしてください。

値を保存する

保存先のパスさえ決定すればデータの書き込みや読み込みは .NET の標準ライブラリで十分対応可能です。 今回はデータを1つのクラスにまとめて JSON 化し文字列を一括で書き込むようにしています。

using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class ButtonEvent : MonoBehaviour
{
  // 省略

  /// <summary>セーブデータ。</summary>
  public class SaveData
  {
    public string Name;
    public string HP;
    public string Attack;
    public string Money;
  }

  /// <summary>
  /// 保存ボタンをクリックしたときの処理。
  /// </summary>
  public void OnClickSave()
  {
    // 保存するデータを作成
    var data = new SaveData()
    {
      Name = InputFieldName.text,
      HP = InputFieldHP.text,
      Attack = InputFieldAttack.text,
      Money = InputFieldMoney.text,
    };

    // オブジェクトを JSON 文字列にシリアライズ
    var json = JsonUtility.ToJson(data);

    // 所定の場所にテキストファイルとして保存
    File.WriteAllText(Path.Combine(Application.persistentDataPath, "SaveData.txt"), json);

    Debug.Log("保存しました。");
  }

  // 省略
}

前回の Tips の内容と .NET 標準ライブラリで対応しているので特に難しいところはないと思います。 まずは実行して保存してみましょう。

パスの場所を見てみるとファイルが保存されていることを確認できると思います。

テキストファイルを開くと入力内容が JSON 形式で保存されていることを確認できます。

今回簡単にファイル書き込みができるように File クラスを使用していますが、StreamWriter など他のクラスを使用して書き込んでも問題ありません。

保存した値を取得する

読み込みも難しいところはないと思います。

/// <summary>
/// 読み込みボタンをクリックしたときの処理。
/// </summary>
public void OnClickLoad()
{
  // 保存されているテキストファイルを読み込む
  var json = File.ReadAllText(Path.Combine(Application.persistentDataPath, "SaveData.txt"));

  // JSON テキストから指定したオブジェクトにデシリアライズ
  var data = JsonUtility.FromJson<SaveData>(json);

  // 読み込んだ値を各フィールドにセット
  InputFieldName.text = data.Name;
  InputFieldHP.text = data.HP;
  InputFieldAttack.text = data.Attack;
  InputFieldMoney.text = data.Money;

  Debug.Log("読み込みました。");
}

保存されたテキストを読み込み、JSON 文字列を JsonUtility.FromJson メソッドでデシリアライズすれば元に戻すことができます。

ゲームを実行して入力フィールドが空の状態から読み込みボタンをクリックして値がセットされることを確認してみてください。

まとめ

Application.persistentDataPath を使用して指定された場所にデータを読み書きすることができました。 ファイルとして保存できるので巨大なデータを保存することも可能です。 ただしこのフォルダパスに保存したデータが複数環境で同期される場合がありますので、 それを想定する場合は大きなサイズのファイルを保存するかどうか、別な場所に保存するかどうかなど考慮したほうがよさそうです。