【Unity初心者】Unityでネットゲームを作りたい【7】PlayFabから読み取ったデータをゲーム内にJsonで保存する～画面に名前を表示してみる


https://qiita.com/ysyss5500/items/4aeb23639a8cf3d67376

### PlayFabから読み取ったデータをゲーム内にJsonで保存する
前回の反省から、今出来ている事を考えた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/f25b7785-e4fc-bc39-4e8f-5e8a1777577a.png)
ﾌﾑﾌﾑ...まだ全然進んでないｗ

そしてお勉強！ゲーム内にJsonファイルとして保存するにはどうすればいいか色々なサイトを回ってお勉強
複雑なのを自分なりに解釈して書き換えて...（コピペで済むのがなかった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/dfd69d68-ab11-5b2e-2cc5-7b65f6afd1b3.png)
```
StreamWriter sw5 = new StreamWriter("Assets/Resources/Item.json", false);
```
ここで保存場所、保存するファイル（ここではItem.josn）を指定
無いとエラー出るからあらかじめ用意しておいた
中身のデータは空でいいみたい
```
 sw5.WriteLine(result.Data["Item"]);
 sw5.Flush();
 sw5.Close();
 ```
 ここで書き込み（PlayFabから取り込んだタイトルデータ）毎回上書き処理
 終わったら次

 これを新規の場合とそれ以外のプレイヤーデータでもやる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/ae706f9a-5fa5-4cb4-a0d6-dde1ea0cca38.png)
ここにあらかじめ指定名前の○○.jsonを作成しておく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/67201798-c8a2-8356-3fa7-caffbafbea9f.png)

うまく行きました
<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/6ee2c4e1-b363-4918-6984-69ea63993ebf.png)

 ここまでたどり着いた！！
```
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;

/// <summary>
/// PlayFabのログイン処理を行うクラス
/// </summary>
[DefaultExecutionOrder(-5)]
public class PlayFabLogin : MonoBehaviour
{
    private bool _shouldCreateAccount;//アカウントを作成するか    
    private string _customID;//ログイン時に使うID
    private string _playerNo;//新規の名前の番号設定

    //タイトルデータJsonを使えるようにするクラス
    //https://qiita.com/ysyss5500/items/7078965fc5ea6e203d55参照
    [Serializable]
    public class Titoruhairetu
    {
        public Item[] item;
    }
    //データ形式が共通なので使いまわす
    [Serializable]
    public class Item
    {
        public string name;
        public int HP;
        public int ST;
        public int DE;
        public int SP;
        public string Rank;
    }
    //プレイヤーデータのJsonを使えるようにするクラス
    [Serializable]
    public class Pdata
    {
        public Item[] pdata;
    }
    [Serializable]
    public class Pmon
    {
        public Item[] pmon;
    }

    //ログイン処理
    public void Start()
    {
        _playerNo = "Py_" + PlayerNo();//新規プレイヤーName作成
        Login();
    }

    /// 新規登録時の初期データ書込み処理
    public void SetUserData()
    {
        PlayFabClientAPI.UpdateUserData(new UpdateUserDataRequest()
        {
            Data = new Dictionary<string, string>() {
            {"PlayerData","{\"pdata\":[{\"name\":\"" + _playerNo  + "\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"},{\"name\":\"アイテム1\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"},{\"name\":\"アイテム2\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"},{\"name\":\"アイテム3\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"}]}"},
            {"PlayerMons","{\"pmon\":[{\"name\":\"スライム1\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム2\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム3\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム4\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム5\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"}]}"}
            }
        },
        result =>
        {
            string aaa = "{\"pdata\":[{\"name\":\"" + _playerNo  + "\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"},{\"name\":\"アイテム1\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"},{\"name\":\"アイテム2\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"},{\"name\":\"アイテム3\",\"HP\":\"0\",\"ST\":\"0\",\"DE\":\"0\",\"SP\":\"0\",\"Rank\":\"N\"}]}";
            string bbb = "{\"pmon\":[{\"name\":\"スライム1\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム2\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム3\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム4\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"},{\"name\":\"スライム5\",\"HP\":\"1\",\"ST\":\"1\",\"DE\":\"1\",\"SP\":\"1\",\"Rank\":\"N\"}]}";
    
            Debug.Log("新規データ書き込み成功");
            //Pdata playerdata = JsonUtility.FromJson<Pdata>(aaa);

            StreamWriter sw = new StreamWriter("Assets/Resources/playerdata.json", false);
            sw.WriteLine(aaa);
            sw.Flush();
            sw.Close();

            //Pmon pmondata = JsonUtility.FromJson<Pmon>(bbb);
            StreamWriter sw2 = new StreamWriter("Assets/Resources/playermons.json", false);
            sw2.WriteLine(bbb);
            sw2.Flush();
            sw2.Close();
        },
        error => {
            Debug.Log("エラーです");
            Debug.Log(error.GenerateErrorReport());
        });
    }

    /// 新規ではない場合のデータ読み込み後Jsonを配列に　例（pmondata.pmon[0].name)
    public void GetUserData()
    {
        var request = new GetUserDataRequest();
        PlayFabClientAPI.GetUserData(request, OnSuccess, OnError);

        void OnSuccess(GetUserDataResult result)
        {
            Debug.Log("通常プレイヤーデータ読込成功");
            //Pdata playerdata = JsonUtility.FromJson<Pdata>(result.Data["PlayerData"].Value);
            StreamWriter sw3 = new StreamWriter("Assets/Resources/playerdata.json", false);
            sw3.WriteLine(result.Data["PlayerData"].Value);
            sw3.Flush();
            sw3.Close();
            //Debug.Log(playerdata.pdata[0].name);
            //Pmon pmondata = JsonUtility.FromJson<Pmon>(result.Data["PlayerMons"].Value);
            StreamWriter sw4 = new StreamWriter("Assets/Resources/playermons.json", false);
            sw4.WriteLine(result.Data["PlayerMons"].Value);
            sw4.Flush();
            sw4.Close();
        }
        void OnError(PlayFabError error)
        {
            Debug.Log("GetUserData: Fail...");
            Debug.Log(error.GenerateErrorReport());
        }
    }

    //タイトルデータ取得して使える配列へ
    public void GetTitleData()
    {
        var request = new GetTitleDataRequest();
        PlayFabClientAPI.GetTitleData(request, OnSuccess, OnError);

        void OnSuccess(GetTitleDataResult result)
        {
            Debug.Log("タイトルデータ読込成功");
            //Titoruhairetu Titoru = JsonUtility.FromJson<Titoruhairetu>(result.Data["Item"]);
            StreamWriter sw5 = new StreamWriter("Assets/Resources/Item.json", false);
            sw5.WriteLine(result.Data["Item"]);
            sw5.Flush();
            sw5.Close();
            //Debug.Log(Titoru.item[10].DE);
        }

        void OnError(PlayFabError error)
        {
            Debug.Log("GetTitleData: Fail...");
            Debug.Log(error.GenerateErrorReport());
        }
    }
    //ログイン実行
    private void Login()
    {
        _customID = LoadCustomID();
        var request = new LoginWithCustomIDRequest { CustomId = _customID, CreateAccount = _shouldCreateAccount };//補足　既にアカウントが作成されており、CreateAccountがtrueになっていてもエラーにはならない
        PlayFabClientAPI.LoginWithCustomID(request, OnLoginSuccess, OnLoginFailure);
    }
    //ログイン成功
    private void OnLoginSuccess(LoginResult result)
    {
        //アカウントを作成しようとしたのに、IDが既に使われていて、出来なかった場合
        if (_shouldCreateAccount == true && result.NewlyCreated == false)
        {
            Debug.LogWarning("CustomId :" + _customID + "は既に使われています。");
            Login();//ログインしなおし
            return;
        }
        //アカウント新規作成できたらIDを保存
        if (result.NewlyCreated == true)
        {
            SaveCustomID();
            ///ここで新規データ書込処理を行う
            SetUserData();
        }
        else
        {
            ///ここで通常ログインでのプレイヤーデータ読込処理を行う
            GetUserData();
        }
            Debug.Log("ログイン成功!!");
        //ここでタイトルデータ読込
        GetTitleData();
    }
    //ログイン失敗
    private void OnLoginFailure(PlayFabError error)
    {
        Debug.LogError("PlayFabのログインに失敗\n" + error.GenerateErrorReport());
    }
    //=================================================================================
    //カスタムIDの取得
    //=================================================================================
    //IDを保存する時のKEY
    private static readonly string CUSTOM_ID_SAVE_KEY = "CUSTOM_ID_SAVE_KEY";
    //IDを取得
    private string LoadCustomID()
    {
        //IDをセーブデータから取得
        string id = PlayerPrefs.GetString(CUSTOM_ID_SAVE_KEY);
        //idの中身がnullもしくは空の文字列("")の場合は_shouldCreateAccountはtrueになる。
        _shouldCreateAccount = string.IsNullOrEmpty(id);　//新規にするには、= true; にする
        //_shouldCreateAccount = true;　//通常ログイン時は= string.IsNullOrEmpty(id);

        //idの中身がない場合、文字列を新規作成
        if (_shouldCreateAccount == true)
        {
            return GenerateCustomID();//文字列を新規作成
        }
        else
        {
            return id;//セーブされた文字列を返す
        }
    }
    //IDの保存
    private void SaveCustomID()
    {
        PlayerPrefs.SetString(CUSTOM_ID_SAVE_KEY, _customID);
    }
    //=================================================================================
    //カスタムIDの生成
    //=================================================================================
    //IDを生成する
    //ユニークな文字列をGuidを使用し生成
    //https://docs.microsoft.com/ja-jp/dotnet/api/system.guid.tostring?redirectedfrom=MSDN&view=netframework-4.8#System_Guid_ToString_System_String_
    private string GenerateCustomID()
    {
        //Guidの構造体生成
        Guid guid = Guid.NewGuid();
        return guid.ToString("N");//書式指定子はNを指定　詳細は「Guid.ToString メソッド」のドキュメント参照
    }
    private static readonly string ID_CHARACTERS = "0123456789abcdefghijklmnopqrstuvwxyz";

    //PlayerNoを生成する
    private string PlayerNo()
    {
        int idLength = 7;//合計10文字ぐらいにしたいので長さを7に設定
        StringBuilder stringBuilder = new StringBuilder(idLength);
        var random = new System.Random();

        //ランダムに生成
        for (int i = 0; i < idLength; i++)
        {
            stringBuilder.Append(ID_CHARACTERS[random.Next(ID_CHARACTERS.Length)]);
        }

        return stringBuilder.ToString();
    }
}
```
ここでJsonを使えるようにする意味がないので消す予定（今はとりあえず//で無効にしてる
確認用とかのをまだ消してないけど、こんな感じで必要データをJsonとして保存できました

そして毎回新規と通常のログインを変更するのがめんどいなーと調べた
たしかUnityのインスペクターで変数を代入できたはず
で、true/falseを毎回書き込むのはめんどいので１かそれ以外と設定
```
   //１の時は新規ログインそれ以外は通常ログイン
   [SerializeField]
   public int han;
```
として
新規か判断しているところに
```
        bool handan;
        if(han == 1) 
        {
            handan = true;
        }
        else
        {
            handan = false;
        }

        //idの中身がnullもしくは空の文字列("")の場合は_shouldCreateAccountはtrueになる。
        _shouldCreateAccount = handan;　//新規にするには、= true; にする
        //_shouldCreateAccount = true;　//通常ログイン時は= string.IsNullOrEmpty(id);

```
としました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/6d0db672-1aaf-5f4f-baa7-4745b51d12a3.png)
ここに紐ずけてあるので選択してインスペクターを見ると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/524c6fa0-9c29-32fd-eb99-8322f0f60a78.png)
記入するところが出てくるので、この数字を1とそれ以外で記入してやったら出来ました
毎回//を消したり付けたりがなくなったので、動作チェックが楽になった

ああ、private bool _shouldCreateAccount;//アカウントを作成するか
これを直接いじればよかったか？
動作チェックしなくなったら戻すのでそれでいいかｗ
 ___
 ### 画面に名前を表示してみる
 以前、[【Unity初心者】Unityでネットゲームを作りたい【3】](https://qiita.com/ysyss5500/items/1338d95f2774e247478a)ここの下の方でチャレンジした[【Unity入門】1分でTextを表示しよう!スコアの表示まで簡単解説!](https://www.sejuku.net/blog/55029)こちらを参照
 で、前にやったJsonファイルの読み込みのやつをとりあえず書いて。。。おお！？
 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/76ab11bd-1e01-20c8-6506-8a144e9e08af.png)

これだけなのにエラーが出ない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/77ce30d8-6d86-a25b-8aa2-1e75d30e5098.png)

おおお～Loginに書いてあるのを参照してる！
シーンが一緒だと大丈夫なのか？？ここに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/d95718dc-ba63-3b7a-861c-c14897669540.png)

この辺書かなきゃ思ってたのにｗ

そして実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3979014/3d594191-3a58-bc14-5d77-d4dbbf65ec40.png)

よし！成功

ちなみに　void Update　に書かないで　void Start　に書いても普通に動いた
繰り返し動かないで済むね～

さあ、前に進んだ、次だ

←前  [【Unity初心者】Unityでネットゲームを作りたい【6】ゲームの流れを考え直さないとダメだ](https://qiita.com/ysyss5500/items/285cbb1478b1141e4408)

[【Unity初心者】Unityでネットゲームを作りたい【8】ビューーの表示を直す～画像ボタンを設置してシーンを切り替えてみた](https://qiita.com/ysyss5500/items/785892928c854f3aa19a)　次→

https://qiita.com/ysyss5500/items/4aeb23639a8cf3d67376