Help us understand the problem. What is going on with this article?

【続】Unityでデータベースと連携させたい!(Firebase編)

More than 1 year has passed since last update.

前回 Firebase とのやりとり部分を Rest Client for Unity というAssetStoreでDLできるライブラリを利用して記述しましたが、今回はその部分を Unity が提供している UnityEngine.Networking クラスの関数(UnityWebRequest,DownloadHandlerBuffer) を使って書き換えてみました!

forqiiita3.png

環境

PC: MacBook Air

前回記事

Unityでデータベースと連携させたい!(Firebase編)

参照記事

UnityWebRequestの使い方【Unity】
UnityWebRequest
DownloadHandlerBuffer
UnityWebRequest HTTP POST to Cloud Functions for Firebase
UnityWebRequestでJSONをPOSTする方法
【C#】クラス名って何?ジェネリッククラスについて。
C#のラムダ式【=>】って何?
C# の delegate : メソッドの引数にメソッドを渡して使用する方法と、JavaScript の function(){} と同じ使用方法( 匿名 )
Unityで覚えるC#
UnityのJsonUtilityの細かい10の疑問をいまさら検証した


:baby_tone2:以下作業内容:baby_tone2:

  • PlayerScores.csを書き換える
- 削除した部分
+ 追記した部分
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
- using Proyecto26;
+ using UnityEngine.Networking;

public class PlayerScores : MonoBehaviour
{
    public Text scoreText;
    public InputField nameText;

    private System.Random random = new System.Random();

    User user = new User();

    public static int playerScore;
    public static string playerName;

    public GameObject targetObject;

    // Start is called before the first frame update
    void Start()
    {
        playerScore = random.Next(0, 101);
        scoreText.text = "Score: " + playerScore;
    }

    public void OnSubmit(){
        playerName = nameText.text;
        PostToDatabase();
    }

    public void OnGetScore(){
        RetrieveFromDatabase();
    }

    private void UpdateScore(){
        scoreText.text = "Score: " + user.userScore;
        ChangeColorName(user.userScore);
    }

    private void PostToDatabase(){
        User user = new User();
-       RestClient.Put("https://forunity-e2ac2.firebaseio.com/"+ playerName +".json",user);
+       string jsonStr = JsonUtility.ToJson(user);
+       StartCoroutine(Put("https://forunity-e2ac2.firebaseio.com/"+ playerName +".json", jsonStr));
        ChangeColorName(user.userScore);
    }

    private void RetrieveFromDatabase(){
-       RestClient.Get<User>("https://forunity-e2ac2.firebaseio.com/"+ nameText.text +".json").Then(response =>
-       {
-       user = response;
-       UpdateScore();
-       });
+       StartCoroutine(GetUserDat("https://forunity-e2ac2.firebaseio.com/"+ nameText.text +".json"));
    }

    private void ChangeColorName(int score){
        //Debug.Log(score);
        if(score < 25){
            // red
            targetObject.GetComponent<Renderer>().material.color = Color.red;
        } else if (score < 50){
            // yellow
            targetObject.GetComponent<Renderer>().material.color = Color.yellow;
        } else if (score < 75){
            // green
            targetObject.GetComponent<Renderer>().material.color = Color.green;
        } else {
            // blue
            targetObject.GetComponent<Renderer>().material.color = Color.blue;
        }

    }
+
+   //SendWebRequest
+   private IEnumerator Put(string url, string jsonStr){
+       //UnityWebRequestを生成する
+       UnityWebRequest request = UnityWebRequest.Put(url, jsonStr);
+
+       //SendWebRequestを実行して送受信開始
+       yield return request.SendWebRequest();
+
+       //エラー判定
+       if(request.isHttpError || request.isNetworkError){
+           //エラーログ
+           Debug.Log(request.error);
+       } else {
+           //結果確認
+           Debug.Log(request.downloadHandler.text);
+       }
+   }
+   private IEnumerator GetUserDat(string url){
+       //UnityWebRequestを生成する
+       UnityWebRequest request = UnityWebRequest.Get(url);
+       request.downloadHandler = new DownloadHandlerBuffer();
+
+       //SendWebRequestを実行して送受信開始
+       yield return request.SendWebRequest();
+
+       //エラー判定
+       if(request.isHttpError || request.isNetworkError){
+           //エラーログ
+           Debug.Log(request.error);
+       } else {
+           // json -> c# で使える形式に直さないとならない...
+           user = JsonUtility.FromJson<User>(request.downloadHandler.text);
+           UpdateScore();
+            
+           //結果確認ログ
+           Debug.Log(request.downloadHandler.text);
+       }
+   }
}

その1

必要なusingを宣言

using Proyecto26;はRest Client for Unityライブラリ用の記述なので削除し、using UnityEngine.Networking;を代わりに追記します

PlayerScores.cs
using UnityEngine.Networking;

その2

登録・更新するファンクションを準備する

登録・更新は UnityWebRequest.Put を使います

PlayerScores.cs
    private IEnumerator Put(string url, string jsonStr){
        //UnityWebRequestを生成する
        UnityWebRequest request = UnityWebRequest.Put(url, jsonStr);

        //SendWebRequestを実行して送受信開始
        yield return request.SendWebRequest();

        //エラー判定
        if(request.isHttpError || request.isNetworkError){
            //エラーログ
            Debug.Log(request.error);
        } else {
            //結果確認
            Debug.Log(request.downloadHandler.text);
        }
    }

その3

取得するファンクションを準備する

取得は UnityWebRequest.Get と DownloadHandlerBuffer を使います

(Get結果を使用するために SendWebRequest() する前に DownloadHandlerBuffer のインスタンスを生成しておかないとならないのと、jsonで取得してきたリクエスト結果をC#で使える形に変換しなければならないところで詰まって結構時間かかりました。。poz)

PlayerScores.cs
    private IEnumerator GetUserDat(string url){
        //UnityWebRequestを生成する
        UnityWebRequest request = UnityWebRequest.Get(url);
        request.downloadHandler = new DownloadHandlerBuffer();

        //SendWebRequestを実行して送受信開始
        yield return request.SendWebRequest();

        //エラー判定
        if(request.isHttpError || request.isNetworkError){
            //エラーログ
            Debug.Log(request.error);
        } else {
            // json -> c# で使える形式に直さないとならない...
            user = JsonUtility.FromJson<User>(request.downloadHandler.text);
            UpdateScore();

            //結果確認ログ
            Debug.Log(request.downloadHandler.text);
        }
    }

その4

準備したファンクションを呼び出すように書き換える

Rest Client for Unity の関数を使っていた部分をそれぞれ準備したファンクションに書き換えます
その際、コルーチンとして扱って呼び出します(Unityはフレームごとにスレッドがすぎていってしまうので、フレームを跨いで処理を中断・再開させることが出来る仕組みであるコルーチンを利用)

Putするデータはjson型で渡したいので、JsonUtility.ToJsonをかましました

PlayerScores.cs
    private void PostToDatabase(){
        User user = new User();
        string jsonStr = JsonUtility.ToJson(user);
        StartCoroutine(Put("https://forunity-e2ac2.firebaseio.com/"+ playerName +".json", jsonStr));
        ChangeColorName(user.userScore);
    }

    private void RetrieveFromDatabase(){
        StartCoroutine(GetUserDat("https://forunity-e2ac2.firebaseio.com/"+ nameText.text +".json"));
    }

修正はこれだけです

(※最終的なPlayerScores.cs)

PlayerScores(修正後).cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class PlayerScores : MonoBehaviour
{
    public Text scoreText;
    public InputField nameText;

    private System.Random random = new System.Random();

    User user = new User();

    public static int playerScore;
    public static string playerName;

    public GameObject targetObject;

    // Start is called before the first frame update
    void Start()
    {
        playerScore = random.Next(0, 101);
        scoreText.text = "Score: " + playerScore;
    }

    public void OnSubmit(){
        playerName = nameText.text;
        PostToDatabase();
    }

    public void OnGetScore(){
        RetrieveFromDatabase();
    }

    private void UpdateScore(){
        scoreText.text = "Score: " + user.userScore;
        ChangeColorName(user.userScore);
    }

    private void PostToDatabase(){
        User user = new User();
        string jsonStr = JsonUtility.ToJson(user);
        StartCoroutine(Put("https://forunity-e2ac2.firebaseio.com/"+ playerName +".json", jsonStr));
        ChangeColorName(user.userScore);
    }

    private void RetrieveFromDatabase(){
        StartCoroutine(GetUserDat("https://forunity-e2ac2.firebaseio.com/"+ nameText.text +".json"));
    }

    private void ChangeColorName(int score){
        //Debug.Log(score);
        if(score < 25){
            // red
            targetObject.GetComponent<Renderer>().material.color = Color.red;
        } else if (score < 50){
            // yellow
            targetObject.GetComponent<Renderer>().material.color = Color.yellow;
        } else if (score < 75){
            // green
            targetObject.GetComponent<Renderer>().material.color = Color.green;
        } else {
            // blue
            targetObject.GetComponent<Renderer>().material.color = Color.blue;
        }

    }

    //SendWebRequest
    private IEnumerator Put(string url, string jsonStr){
        //UnityWebRequestを生成する
        UnityWebRequest request = UnityWebRequest.Put(url, jsonStr);

        //SendWebRequestを実行して送受信開始
        yield return request.SendWebRequest();

        //エラー判定
        if(request.isHttpError || request.isNetworkError){
            //エラーログ
            Debug.Log(request.error);
        } else {
            //結果確認
            Debug.Log(request.downloadHandler.text);
        }
    }
    private IEnumerator GetUserDat(string url){
        //UnityWebRequestを生成する
        UnityWebRequest request = UnityWebRequest.Get(url);
        request.downloadHandler = new DownloadHandlerBuffer();

        //SendWebRequestを実行して送受信開始
        yield return request.SendWebRequest();

        //エラー判定
        if(request.isHttpError || request.isNetworkError){
            //エラーログ
            Debug.Log(request.error);
        } else {
            // json -> c# で使える形式に直さないとならない...
            user = JsonUtility.FromJson<User>(request.downloadHandler.text);
            UpdateScore();

            //結果確認ログ
            Debug.Log(request.downloadHandler.text);
        }
    }
}

→ 問題なく登録・更新・取得できました!!


:alien:振り返り:alien:

前回 Rest Client for Unity というライブラリを使った Firebase とのやりとり部分を Unity提供の関数を使ったらどんな記述になるのかな、と思い立って書き換えてみましたが、
そもそもC#に不慣れなので、コルーチンやらラムダ式やらも調べつつで丸一日費やし、Unityの先生に助言もいただき、なんとか書き換えることができました。。。prz

感想としては、便利なライブラリはとってもありがたいものなんだな、です!
これからは便利ライブラリをバンバン使って実装時間を短縮して作りたいものを早く作る方に重点を置いて行きたいなと思いました!

以上!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした