i-school - VRアクションゲーム 取得したアイテムのセーブ・ロード機能
 アイテムの名前をデータセーブ用の Key として利用し、所持しているアイテムの種類と個数をセーブ・ロードします。


<実装動画>
動画ファイルへのリンク



 新しい学習内容は以下の通りです。

 ・PlayerPrefs クラスと各メソッド ーSet〜 メソッド、Save メソッド、Get〜 メソッド、HasKey メソッド、DeleteAll メソッドー



設計


 インベントリに管理されている所持(獲得)アイテムの情報をセーブ・ロードする機能を実装します。

 まずはサーバーへのセーブ・ロードではなく、Unity の PlayerPrefs クラスを利用し、デバイス内にセーブして、そのデータをロードするようにします。
それが問題なく動作することが確認できてから、サーバーでのセーブ・ロードを検討します。

 PlayerPrefs クラスでデータをセーブ・ロードする際には、保存が可能な型と、その情報を保存するための Key の情報が必要になります。
Key は string 型で指定します(Key はラベルのようなものであり、名前を付けて保存するイメージです)。

 そのため今回は、ItemData クラスにある string 型の itemName 変数を Key に利用し、そのアイテムの所持数(int 型)をセーブ・ロードします。
itemName 変数は保存するためのラベルの役割とアイテムの種類を特定するための2つの目的に利用しています。


GameData スクリプトを修正する


 インベントリ機能は GameData クラスで管理されているため、セーブ・ロードの機能も同じく GameData クラス内に新しく作成します。
合わせて、アイテムの持つスコアの合計値などを計算する機能も実装しておきます。

 セーブ・ロードの機能をメソッドとして作成しておくことで、いずれのクラスからでもセーブ・ロードの機能を実行できるようにしています。
今回はまず、他のクラスにメソッドの実行命令を記述しなくてもデバッグが行えるように、新しく Update メソッドを追加し、
ボタン操作時にセーブ・ロードの機能を実行できるようにしています。

 こういったデバッグ機能も自分で設計して用意しておけるように考えてみてください。


GameData.cs

<= クリックすると開きます



<PlayerPrefs クラスと各メソッド ーSet〜 メソッド、Save メソッド、Get〜 メソッド、HasKey メソッド、DeleteAll メソッド>


 Unity ではデータのセーブ・ロードを行うための PlayerPrefs クラスが用意されています。
PlayerPrefs クラスにはセーブ・ロード用のメソッドや、データの確認メソッド、削除用のメソッドなどが用意されていますので、
こちらを実装することで指定したデータをセーブしたり、ロードしたりすることが可能になっています。

 データの保存先は、Unity Editor や PC ゲームの場合には PC 本体のハードディスク、Web の場合はブラウザ内、スマホ端末の場合にはアプリ内のデータの場所内です。
VR の場合には、オキュラスクエストのデバイス内になります。


<PlayerPrefs クラス>
https://docs.unity3d.com/ja/current/ScriptReferenc...


 2つのメソッドを利用してセーブを行いますので、順番に説明します。


1.Set〜 メソッド

 Key という文字列を保存する際の識別子として指定し、その名前を用いて指定された型の情報をセーブするための準備(予約)を行います。
Key とはいわばセーブ用のラベルであり、名前を付けて保存のことです。この Key の情報をロードする際にも利用します。

 PlayerPrefs クラスにはセーブの方法が3種類用意されており、Set 〜 で始まる命名規則になっています。今回利用している SetInt メソッドもその1つです。
SetInt という名前の通り、int 型の情報をセーブしておくことが出来ます。残る2つは SetString メソッド、SetFloat メソッドであり、これらもメソッド名と同名の型の情報をセーブします。

 今回セーブしたい情報は GameData クラスで管理している InventryData クラスの int 型の itemCount 変数です。つまり、指定されたアイテムの所持数です。
int 型の情報であれば SetInt メソッドを実行することで、セーブの準備(予約)ができます。


 for (int i = 0; i < inventryDatasList.Count; i++) {
    PlayerPrefs.SetInt(inventryDatasList[i].itemData.itemName, inventryDatasList[i].itemCount);
  }

 SetInt メソッドの第1引数が Key になります。メソッドの引数で届いている key の情報をそのまま利用しています。

 SetInt メソッドの第2引数がセーブされる値(int 型)になります。

 Set 〜 で始まる3つのメソッドは、セーブを行う対象を設定しています。そのためセーブするための情報をセットして準備を行うメソッドです。
実際には次に解説する Save メソッドを実行することでデータがセーブされます。


参考サイト
Unity公式スクリプトリファレンス
PlayerPrefs.SetString
https://docs.unity3d.com/ja/current/ScriptReferenc...


2.Save メソッド

 Set 〜 メソッドによって準備された情報をセーブするメソッドです。
この処理が実行されて始めてデータがセーブされます

 Save メソッドよりも前に、複数の Set 〜 メソッドが実行されていた場合、この Save メソッドはそれらすべての Set 〜 メソッドのセーブを行います

 // アイテムの数だけ、セーブの準備
  for (int i = 0; i < inventryDatasList.Count; i++) {
    PlayerPrefs.SetInt(inventryDatasList[i].itemData.itemName, inventryDatasList[i].itemCount);
  }

  // セーブ実行(準備した SetInt メソッドの内容がすべて1回でセーブされる)
  PlayerPrefs.Save();

 今回の場合には、int 型の整数の情報をセーブしています。
Save メソッドの実行回数は1回ですが、SetInt メソッドはアイテムの種類分だけ実行されて、それぞれのデータとして保持されています。
つまり、1つのデータとしてセーブされている訳ではなく、個々のアイテムごとに1つずつのセーブデータが作られています。


参考サイト
Unity公式スクリプトリファレンス
PlayerPrefs.Save
https://docs.unity3d.com/ja/current/ScriptReferenc...


3.Get〜 メソッド

 PlayerPrefs クラスに用意されている、ロード用のメソッドです。Set 〜 メソッドに対応できるように、こちらにも3つのメソッドが用意されています。
今回は SetInt メソッドで int 型の情報をセーブしていますので、ロードする場合には、GetInt メソッドを利用して行います。

 Get 〜 メソッドの第1引数には、Key を指定します。
PlayerPrefs 内にセーブされている Key が存在しているかを検索・照合し、Key が存在している場合、その情報を指定した型で取得するメソッドです。
取得した値は戻り値として提供されます。そのため、Get 〜 メソッドを実行する場合には、左辺に戻り値を受け取るための変数を準備しておく必要があります
今回は、GetInt メソッドですので、セーブされている Key が存在している場合には、int 型で取得、つまりロードを行う処理になります。

 Get 〜 メソッドは第2引数を設定することで、もしも Key が存在しなかった場合には、第2引数に指定した値を Default 値として設定を行うことも出来ます。
 
 // インベントリにアイテムのデータを追加して復元
  AddIndentryDatasList(PlayerPrefs.GetInt(DataBaseManager.instance.itemDataSO.itemDatasList[i].itemName, 0), itemData);

 上記処理のうち、引数内の

 PlayerPrefs.GetInt(DataBaseManager.instance.itemDataSO.itemDatasList[i].itemName)

 この部分がデータのロードをしている部分

 GetInt メソッドで取得した情報は int 型ですので、その値が itemCount 変数に代入されることで、ロード処理を完了しています。
第2引数に 0 を設定していますので、万が一、 Key の情報がセーブされていない場合には、 0 を代入する処理を行います。

参考サイト
Unity公式スクリプトリファレンス
PlayerPrefs.GetString
https://docs.unity3d.com/ja/current/ScriptReferenc...


4.HasKey メソッド

 引数に指定した文字列が PlayerPrefs に保存されている Key の情報としてあるかを調べて、Key が存在している場合には true、存在していない場合には false を戻します。

  // アイテムのデータベース内とセーブされているデータのアイテムの名前とを1つずつ順番に照合
  for (int i = 0; i < DataBaseManager.instance.itemDataSO.itemDatasList.Count; i++) {
  
     // セーブされている情報にアイテムの名前が合致しているデータが見つかった場合
      if (PlayerPrefs.HasKey(DataBaseManager.instance.itemDataSO.itemDatasList[i].itemName)) {
    

 今回のケースでは、for 文内で if 文の条件式として記述して、アイテムデータにあるアイテムの名前と、保存されているアイテムの名前が一致するかを判定しています。
セーブする際の Key にアイテムの名前を設定していますので、その存在がない場合(false)と存在する場合(true)とで異なる値を戻すようになっています。

参考サイト
Unity公式スクリプトリファレンス
PlayerPrefs.HasKey
https://docs.unity3d.com/ja/current/ScriptReferenc...


5.DeleteAll メソッド

 PlayerPrefs 内にセーブされているすべての情報をまとめて削除するメソッドです。
この操作は Unity エディターから実行することも可能です。主にデータをリセットする際に利用しますので、
ゲームのデータを初期化してデバッグを行う際にも利用できます。

 Key 単位で削除する DeleteKey メソッドもあります。

 
 // すべてのセーブデータを削除
  PlayerPrefs.DeleteAll();

参考サイト
Unity公式スクリプトリファレンス
PlayerPrefs.DeleteAll
https://docs.unity3d.com/ja/current/ScriptReferenc...
Unity公式スクリプトリファレンス
PlayerPrefs.DeleteKey
https://docs.unity3d.com/ja/current/ScriptReferenc...


 以上です。
自由に処理を作成して、どのように動くかを確認してみてください。


ゲームを実行して動作を確認する


 ゲームを実行し、インベントリに任意のアイテムを追加します。
その状態でセーブ用のボタンを押し、ゲームを終了します。

 再度ゲーム実行後、今後はロード用のボタンを押してください。
GameData のインベントリにセーブしておいたデータがロードされて復元されれば成功です。
ロードする際には、アイテムのスクリプタブル・オブジェクトの ItemName 変数の値とセーブしている際に利用している ItemName 変数の値とを照合しています。
アイテムの数も復元されていることを確認しておいてください。


<セーブ時のインベントリ>



<アイテムのスクリプタブル・オブジェクト>



<実装動画>
動画ファイルへのリンク




 以上でこの手順は終了です。