はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity,GAS】UnityからGoogleAppsScriptにGET,POSTしてデータ管理をする

はじめに

今回はUnityからGoogleAppsScriptを使ってデータ管理をしてみようという記事になります!

ゲームを開発をするにあたって、ランキングやユーザーのデータを管理する必要があるかもしれません。

これを実現するためにはいわゆるサーバーというものが必要になるのですが、最近はいろんなサービスが登場してきています。

一番個人でも活用できて、なるべくアプリの容量を増やしたくなければニフクラといわれるものがいいと思います。

www.hanachiru-blog.com

ただしAPIに上限回数があったりもっと柔軟に色々やりたいならば、GoogleAppsScript(GAS)というGoogleがサーバーを無料で提供してくれるプログラミング環境を用いるのも一つの手だと思います。

これを応用することで、本当に色々なことができてマニアック(?)な人気があるものです。

今回はこれを使ってUnityとGASでデータのやり取りをしてみようと思います。

GAS側のコードの実装

GASはJavaScriptもしくはTypeScript言語で書かなければならのですが、私は全くのど素人なのでコードはアレかもしれないのであしからず。

今回はC#と似たようにかけるTypeScriptを使って書いていきますが、JavaScriptでもさほど変わりません。
追記) やっぱりJavaScriptにしました

REST APIを使ってやり取りするに当たって、まずはHTTPのGETメソッドでリクエストされた場合の処理を書きます。

// GETメソッドで実行される
function doGet(e){
    // 「url?point=10」というGETメソッドなら10が格納される
    const point  = e.parameter.point;

    // データを加工しありスプレッドシートを操作したり
    const value = 0;

    // レスポンスとしてJsonを返す
    const response = JSON.stringify({key: value});
    let output = ContentService.createTextOutput();
    output.setMimeType(ContentService.MimeType.JSON);
    output.setContent(response);
    return output;
}

クエリパラメータを受け取るときにはe.parameter.「パラメータの名前」のようにしてください。

あとはレスポンスを返すときの定型文をかけばOKです。


次にHTTPのPSOTメソッドで送られてきた場合の処理を書きます。

// POSTメソッドで実行される
function doPost(e){
    //  パラメータでJsonを受け取り、パース
    const jsonString = e.postData.getDataAsString();
    const data = JSON.parse(jsonString);
    let point = data.point;

    // データを加工しありスプレッドシートを操作したり
    const value = 0;

    // レスポンスとしてJsonを返す
    const response = JSON.stringify({ message: "succeeded" });
    let output = ContentService.createTextOutput();
    output.setMimeType(ContentService.MimeType.JSON);
    output.setContent(response);
    return output;
}

JSONを返すところは変わりませんが、パラメータを受け取る箇所が異なることに注意してください。

また基本的にサーバーになにかしらデータを送るとき(自分のスコアをセーブとか)は『POST』,単にデータを取得するだけのとき(ランキングの取得とか)に『GET』を使ってください。

これを間違えると不正をされてしまう可能性が爆上がりです。(POSTでも確実に安全というわけではないですが・・・)

Unity側の実装(GET)

Unity でGETをリクエストする例を書いてみました。

UnityにはUnityWebRequestというWebサーバーとのやり取り専用のクラスがあるのでそちらを用いました。
Networking.UnityWebRequest - Unity スクリプトリファレンス

もし非同期でやり取りしたいなどが場合はC#標準のHttpClient等を使うと良いでしょう。

またレスポンスのパラメータに対応したJSONを作るところだけ注意してください。

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class Test : MonoBehaviour
{
    private const string URI = "https://script.google.com/macros/s/---------------";

    private void Start()
    {
        StartCoroutine(Get());
    }

    public IEnumerator Get()
    {
        int point = 10;
        UnityWebRequest request = UnityWebRequest.Get($"{URI}?point={point}");

        yield return request.SendWebRequest();

        if (request.isHttpError || request.isNetworkError)
        {
            Debug.Log(request.error);
        }
        else
        {
            var result = request.downloadHandler.text;
            var response = JsonUtility.FromJson<ResponseData>(result);
            Debug.Log(response.key);        // 0
        }
    }

    [System.Serializable]
    public class ResponseData
    {
        public int key;
    }
}

Unity側の実装(POST)

次にPOSTをしてみましょう。

using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

public class Blog : MonoBehaviour
{
    private const string URI = "https://script.google.com/macros/s/---------------";

    private void Start()
    {
        StartCoroutine(Post());
    }

    public IEnumerator Post()
    {
        int point = 10;
        var jsonBody = $"{{ \"point\" : \"{point}\" }}";
        var request = new UnityWebRequest(URI, "POST");
        byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonBody);
        request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
        request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        yield return request.SendWebRequest();

        if (request.isHttpError || request.isNetworkError)
        {
            Debug.Log(request.error);
        }
        else
        {
            var result = request.downloadHandler.text;
            var response = JsonUtility.FromJson<ResponseData>(result);
            Debug.Log(response.message);        // succeeded
        }
    }

    [System.Serializable]
    public class PostData
    {
        public int point;
    }

    [System.Serializable]
    public class ResponseData
    {
        public string message;
    }
}

さいごに

あとはスプレッドシートをデータベース代わりにすれば、お手軽データベースの完成です。
www.hanachiru-blog.com

基本的にGoogleのサーバーなのでサーバーが落ちたり等はほぼないと思いますが、速度が少し遅いのだけがネックではあります。

結構GAS特有のスピードアップ方法などがあるので実際に使う時は色々と調べてみてください。

あとは自前な分セキュリティ面が少し心配です。

しかし可能性が無限大というところは間違いありません。

是非うまく活用してみてください。

ではまた。