【JSON】UnityのJSONでのセーブについて解説してみた【ファイル出力、入力編1/2】

ファイル Unity

前回の記事の続きです。

【JSON】UnityのJSONでのセーブについて解説してみた【表示編】
この記事でのゴールはUnityのConsoleにJSON形式のデータを表示させることです。この記事のゴールのコードを載せます。 最初は①と②に目を通すだけで大丈夫です。

また、今回はファイルの出力、入力です。
詳しくないのでわかりませんが、ファイルの出力、入力関連はいつも以上に怖いので私のサイトを参考にする際は自己責任でお願いいたします

UnityのJSONについては引き続きこちらのサイトを参考にさせていただきました。

【Unity入門】5分で簡単解決!JSON形式のデータを扱う方法 | 侍エンジニアブログ
この記事では「 【Unity入門】5分で簡単解決!JSON形式のデータを扱う方法 」といった内容について、誰でも理解できるように解説します。この記事を読めば、あなたの悩みが解決するだけじゃなく、新たな気付きも発見できることでしょう。お悩みの方はぜひご一読ください。
2019年3月23日 | くろくまそふと
ゲーム制作ブログ

全体像

まず最初に完成したコードの画像を見せます



途中で途切れてしまってすいません!
青い枠で囲ったコードは前回の記事で書いたコードと同じです。
①、②、③、④の順に説明していきます。

①はセーブの処理。
②はロードの処理。
③はセーブボタンを押したときの処理。
④はロードボタンを押したときの処理。
です。

Unityで実装したときの画像はこのようになります。
空のGameObjectにTestスクリプトをアタッチして、ボタンを二つ作りセーブとロードをできるようにします。

その前に

大事なことを忘れていました。
ファイルを扱うときは上の画像の4行目と同じように

Using SystemIO;

書き加えてください。

セーブの処理(①の説明)

まず①のコードを載せます。

public void Save(SaveData saveData)
    {
        StreamWriter writer;

        string jsonstr = JsonUtility.ToJson(saveData);

        writer = new StreamWriter(Application.dataPath + "/savedata.json", false);
        writer.Write(jsonstr);
        writer.Flush();
        writer.Close();
    }

このコードは最初に
public void Save(SaveData saveData)
とありますが、これはSaveData型の値を受け取るという意味です。
なので、このメソッドを呼び出すときは
Save(SaveData型のインスタンス)
のように呼び出します。

StreamWriter writer
では、StreamWriterクラスのインスタンスwriterを作っています。
StreamWriterクラスについてはこちらのサイトに詳しく載っています。

StreamWriter クラス (System.IO)
文字を特定のエンコーディングでストリームに書き込むための TextWriter を実装しています。Implements a TextWriter for writing characters to a stream in a particular encoding.

ただ、こちらのサイトではusingステートメントというものを使っており、今回のやり方とは違うコードになっています。
usingステートメントについては後で私の分かる範囲で説明してみます。

string jsonstr = JsonUtility.ToJson(saveData);
では、前回の記事で説明したようにJsonUtility.ToJsonメソッドsaveDataをJSON形式に変換して、string型のjsonstrに代入しています。

writer = new StreamWriter(Application.dataPath + “/savedata.json”, false);
では先ほど作ったStreamWriterクラスのインスタンスwriterにファイルを書き込むパスを代入しています。
第二引数をfalseにしていますが、falseだと上書き、trueだと追加で書き込まれるようです。

今回パスの場所は
Application.dataPath + “/savedata.json”
にしました。
Windowsでこのパスを代入すると、そのプロジェクトのAssetファイルの中にファイルが書き込まれます。
Macでも恐らく同じ場所だと思います。
パスについてはこちらのサイトに詳しく書いてありました。

【Unity3D】ファイル保存パス - Qiita
ファイル保存パス 自分メモとしてまとめました。 ※Androidの外部ストレージは端末によってパスが変わります。 Application.dataPath アプリケーションが保存されているパス。 環境 取得パス ...

writer.Write(jsonstr);
writer.Flush();
writer.Close();

ここではWriterメソッドを使い、jsonstrのデータを書き込んでいます。
Flushメソッドはデータを確実に書き出すためのコードのようです。
Closeメソッドはストリームを閉じるコードのようです。
とても重要なコードのようですが、あまり詳しく説明できないので(申し訳ないです)、サイトの説明の引用とURLを載せます。

現在のライターで使用したすべてのバッファーをクリアし、バッファー内のすべてのデータを基になるストリームに書き込みます。
StreamWriter.Flush メソッド (System.IO) | Microsoft Docsより引用

StreamWriter.Flush メソッド (System.IO)
現在のライターで使用したすべてのバッファーをクリアし、バッファー内のすべてのデータを基になるストリームに書き込みます。Clears all buffers for the current writer and causes any buffered data to be written to the underlyin...

現在の StreamWriter オブジェクトと基になるストリームを閉じます。
StreamWriter.Close メソッド (System.IO) | Microsoft Docsより引用

StreamWriter.Close メソッド (System.IO)
現在の StreamWriter オブジェクトと基になるストリームを閉じます。Closes the current StreamWriter object and the underlying stream.

ロードの処理(②の説明)

②のコードを載せます。

public SaveData Load()
    {
        if (File.Exists(Application.dataPath + "/savedata.json"))
        {
            string datastr = "";
            StreamReader reader;
            reader = new StreamReader(Application.dataPath + "/savedata.json");
            datastr = reader.ReadToEnd();
            reader.Close();

            return JsonUtility.FromJson<SaveData>(datastr);
        }

        SaveData saveData = new SaveData();
        saveData.player_name = "";
        saveData.player_level = 1;
        return saveData;
    }

最初に
public SaveData Load()
とあります。
これは戻り値にSaveData型の値を返すという意味です。

35行目、41行目に
return
と書いて値を返しています。(2つreturnがあるのはif文があるからです)

このメソッドを呼び出すときは
SaveData saveData = Load()
という感じで呼び出します。

if (File.Exists(Application.dataPath + “/savedata.json”))
というコードはApplication.dataPath + “/savedata.json”ファイルがあるかを確認しています。

もしなかった場合は
SaveData saveData = new SaveData();
saveData.player_name = “”;
saveData.player_level = 1;
return saveData;
という処理をしています。
セーブデータがなかった場合の処理なので、player_nameを””で空にplayer_levelを1にしています。

File.Existsについては、こちらのページに詳しく書いてあります。

File.Exists(String) メソッド (System.IO)
指定したファイルが存在するかどうかを確認します。Determines whether the specified file exists.

string datastr = “”;
ではstring型のdatasr変数を作り、空の文字列を宣言しています。

StreamReader reader;
reader = new StreamReader(Application.dataPath + “/savedata.json”);
datastr = reader.ReadToEnd();
reader.Close();
こちらは先ほどのStreamWriterの処理とかなり似ています。
StreamReaderクラスのインスタンスreaderを作り、
readerにパスを代入し、ReadToEndで読み込みdatastrに代入して、Closeメソッドで閉じています。

return JsonUtility.FromJson<SaveData>(datastr);
では前回の記事で説明した通り、datastrに代入されているJSON形式のデータをSaveDataに代入して、それをreturnで返しています。

StreamReaderについては、こちらのページに詳しく書いてあります。

StreamReader クラス (System.IO)
特定のエンコーディングのバイト ストリームから文字を読み込む TextReader を実装します。Implements a TextReader that reads characters from a byte stream in a particular encoding.

セーブボタンを押したときの処理(③の説明)

③のコードを載せます。

 public void PushSaveButton()
    {
        SaveData saveData = new SaveData();
        saveData.player_name = "かみこっぷ";
        saveData.player_level = 2;
        Save(saveData);
    }

最初にSaveData型のインスタンスsaveDataを作り、
saveData.player_nameにかみこっぷ
saveData.player_levelに2を代入しています。

次に、SaveメソッドにsaveDataを渡して処理させています。
これでplayer_nameにかみこっぷ、player_levelに2が入った状態で処理(セーブ)されます。

ロードボタンを押したときの処理(④の説明)

④のコードを載せます。

public void PushLoadButton()
    {
        SaveData saveData = Load();
        Debug.Log(saveData.player_name);
        Debug.Log(saveData.player_level);
    }

こちらではSaveDataのインスタンスsaveDataを作り、Loadメソッドの値を入れています。
次に、そのロードされたデータをDebug.Logで表示させています。

おまけ usingステートメントについて

最初にこちらのサイトを参考にさせていただきました。

ファイル操作
概要 System.IO 名前空間以下に、ディレクトリ(フォルダ)・ファイルの作成・読み書き等を行うためのクラスが用意されています。 ファイル操作などの処理は、 オブジェクト指向言語との相性もいいですし、 C#…
【C#入門】usingステートメントで自動開放(Dispose、Closeの代替) | 侍エンジニアブログ
この記事では「 【C#入門】usingステートメントで自動開放(Dispose、Closeの代替) 」といった内容について、誰でも理解できるように解説します。この記事を読めば、あなたの悩みが解決するだけじゃなく、新たな気付きも発見できることでしょう。お悩みの方はぜひご一読ください。

usingステートメントは名前空間とは全く違うもので、Closeメソッド等を書く必要がなく、便利なコードのようです。

未確認飛行さんのサイトのStreamReader,StreamWriterのコードの@”testtest.txt”を@”test.txt”にしたところ、Assetファイルの一個上のプロジェクトファイル内に作られるのを確認できました。
@”testtest.txt”の@を消してApplication.dataPath + “/text.txt”にしたところ、Assetにsavedata2が作られるのを確認できました。

これ以上は私には分からないので、各自で調べていただけると助かります。

次の記事

【JSON】UnityのJSONでのセーブについて解説してみた【ファイル出力、入力編2/2】
前回の記事の続きです。今回はUnityで実装していきます。こちらの記事でも引き続き私のサイトを参考にする場合は自己責任でお願いいたします。UnityのJSONについては引き続きこちらのサイトを参考にさせていただきました。...

コメント

タイトルとURLをコピーしました