Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Unity]Runtimeでスプレッドシートの情報をJsonで受け取り反映する

More than 3 years have passed since last update.

○経緯

  • 仕事でアプリのプロトタイプを作る事になりました。
  • パラメータなどはエクセルで用意されていました。
  • 「NPOIとエディタプログラムで作れるから!」と経験もかねて後輩にインポータを作ってもらいました。
  • しかし頻繁にパラメータ調整を行う羽目になりつつありました。
  • 逐一反映とかの手順踏むのめんどくさい。
  • サーバーサイドの上司が簡易なWeb画面を用意してくれました。
  • けどアプリ起動時にスプレッドシートのデータ取り込めばええやんと、業務後に家でのんびりやり方を模索する事にしました。

○環境

  • Windows64bit、Unity 5.5.0f3、無料の外部アセット(Json.NET Converters - Simple compatible solution)
  • Androidの実機テストは後ほどやる予定です。iOSに関しては家にMacが無いので…(´・ω・`)
  • もしかするとビルド設定や動的コンパイルなどで引っかかるかもしれません…。

○先に結論

○成果物

  • Githubにあります。https://github.com/cyber1496/GAS
  • サンプルの実行方法などは付属のREADMEを見てください。
  • GoogleDrive上のスプレッドシートにアクセスする必要があるためいくつか手順を踏む必要があります。

○事前準備

○細かな実装など

◆呼び出し

シートごとにデータの構造を変えることを考慮しシート名を指定させてます。
ジェネリックで型を指定し、通信処理が終わったらActionが呼び出されるようにしました。

StartCoroutine(
    GetData<データ型>(シート名,
        dataArray =>
        {
            foreach (var data in dataArray)
            {
                Debug.Log(data.ToString()));
            }
        }
    )
);

◆データ取得

UnityWebRequestを使いました。
Json.NET Convertersがとても気持ちよく使えて良かったですね。

IEnumerator GetData<T>(string sheetName, System.Action<T> action)
{
    var request = CreateRequestGetSheetJson(sheetName);
    if (request == null)
    {
        yield break;
    }
    yield return request.Send();
    if (request.isError)
    {
        Debug.LogError(request.error);
    }
    else
    {
        action(JsonConvert.DeserializeObject<T>(request.downloadHandler.text));
    }
}

◆通信リクエスト

ひとまず GETで欲しいシート名渡せればええやろ…と

UnityWebRequest CreateRequestGetSheetJson(string sheetName)
{
    return UnityWebRequest.Get(
        string.Format("{0}?{1}&{2}",
                        WebAPIのURL,
                        Param("sheetId", スプレッドシートのID),
                        Param("sheetName", sheetName))
        );
}
string Param(string key, string param)
{
    return string.Format("{0}={1}", key, param);
}

◆(追記)スプレッドシート側のGoogleAppsScript

記事のタグにGoogleAppsScriptを付けているにも関わらず触れておりませんでした。
Google SpreadSheet のデータを JSON 形式で取得する Web API をサクッと作るで掲載されていらっしゃる内容を流用させて頂いています。

function getData(id, sheetName) {
  var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName);
  var rows = sheet.getDataRange().getValues();
  var keys = rows.splice(0, 1)[0];
  return rows.map(function(row) {
    var obj = {}
    row.map(function(item, index) {
      obj[keys[index]] = item;
    });
    return obj;
  });
}
function doGet(e) {
  var id = e.parameter.sheetId;
  var data = getData(id, e.parameter.sheetName);
  return ContentService.createTextOutput(JSON.stringify(data, null, 2))
  .setMimeType(ContentService.MimeType.JSON);
}

○所感

  • レスポンスは遅いです。頻度は少なくした方が良いでしょう。
  • 前職では家庭用ゲームやスロパチ業務が多かったので動的に内部のパラメータが変わるのは高まりますね。
  • ちょっとしたプロトタイプの作成のパラメータはもうこれで良いんじゃないか感。
  • クライアントプログラマだけでデータ構造の変更とデシリアライズが完結するのは良いなと思います。本番の通信が入ったとしても通信個所を見直すだけで動作が保証できそうかなと思いますし…。
  • GoogleAppsScriptをもう少し知れば業務改善が捗りそうです。Unity以外でも色々用途は思い浮かびますね。
  • 艦●れで一時期友人とスプレッドシートで編成表とか出撃記録を共有していたのでそういう使い方のツールも色々浮かびます。

以上です。

Qiitaへは初投稿でしたが記事のまとめで2時間は使い過ぎたなぁと思っちゃいますね。
おかげで明日は何時に起きられるのやら…。閃●カグラが届いたばかりなのになぁ…。

cyber1496
ゲーム系エンジニア。ここ数年はUnityを使い倒しモバイル向けゲームを作っています。
https://twitter.com/cyber1496
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