【Unity】Google Spreadsheetsでリアルタイムにパラメーター調整する話
初めに
まず、チームでゲームを制作する際、一つ問題になるのがゲームのバランス調整をどのように行うのかということです。
基本的にチームのプランナーが行うと思うのですが、例えばデータをエクセルに書いてプログラマーに渡すといったやり方はデータの受け渡しやデータの差し替えなどが非常に大きなコストになります。
UnityやUE4などのゲームエンジンを使って直接調整していたり、gitなどを使ってデータを管理している場合もビルドやそもそもツールを起動するなど手間がかかります。
なのでそれらの反映をできる限り簡単したいということで、GoogleのSpreadsheetsとGoogle Action Script(以下GAS)を使ってリアルタイムに実機で調整できるようにします。
Google Spreadsheetsとは
ざっくり言ってしまうとGoogleが提供しているブラウザ版のExcelです。
- 複数人での同時編集が可能
- 共有が楽ちん
- 通信で取得することが可能 大体この辺が特徴でしょうか。
ここで提供されているGASというAPIを活用することでデータを取得したり逆にデータを書き込むといったことも可能です。(超便利!)
実際にGoogle SpreadSheetのデータを取れるようにする
function test() { Logger.log(SpreadsheetApp.getActiveSpreadsheet().getId()); }
function doGet(e) { var sheetName = e.parameter.sheetName; var sheet = SpreadsheetApp.openById('調べたID'); if (sheet.getSheets().some(function(s) { return s.getSheetName() === sheetName; })) { var ss = sheet.getSheetByName(sheetName); //シートに書かれている情報をすべてJSONにして投げる var json = ss.getDataRange().getValues(); return ContentService .createTextOutput(JSON.stringify(json)) .setMimeType(ContentService.MimeType.JSON); } }
- これを新たに書き込んだら公開→webアプリケーションとして導入
- アプリケーションにアクセスできるユーザーを全員(匿名ユーザーを含む)に設定して公開
これでスプレッドシートの情報が取れるようになりました。
Unity上でデータを扱う
Unity上でデータを取得するにはWWWかUnityWebRequestを使ってデータを取得し、その取得したデータをJSONからクラスなどにパースして扱います。
この際、やり方はとてもたくさんあるのですが今回はUnityWebRequestとminiJSONを使っています。
このやり方はお手軽かついろいろなバージョンで動くのですが処理的にはかなり無駄が多いのでもし調整以外の目的で使う場合はUnityWebRequestやJSONUtilityなどを使ったり取得するデータの範囲をきちんと指定するなどして最適化してください。
using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using MiniJSON; public class SpreadsheetsManager : MonoBehaviour { //ダウンロードしたデータを格納する。 [SerializeField] List<Character> downloadData = new List<Character>(); private IEnumerator LoadGoogleSpreadSheet(string _sheetName) { string URL = "https://script.google.com/macros/s/AKfycbyj8ZQoHjnnxii_KH2Wj1NmNRdMn0mRNAgfSXYqhQHb5UtiAmY/exec"; var download = UnityEngine.Networking.UnityWebRequest.Get(URL + "?sheetName=" + _sheetName); yield return download.SendWebRequest(); //JSONの読み込みにはminiJSONを使用 var json = (List<object>)Json.Deserialize(download.downloadHandler.text); if (json != null) { //先頭一行目は無視、本来は無視しないようにデータを送るべき for (int i = 1; i < json.Count; i++) { var tex = (List<object>)json[i]; string[] str = tex.Select(n => n.ToString()).ToArray(); Character chara = downloadData[i - 1]; //先頭一列目は無視 chara.charaID = str[1]; chara.charaName = str[2]; chara.hp = int.Parse(str[3]); chara.Attack = int.Parse(str[4]); } } else { Debug.LogError(download.downloadHandler.text); } for(int i=0;i< downloadData.Count;i++) { downloadData[i].ReflectState(); } } void Start () { StartCoroutine(LoadGoogleSpreadSheet("Sheet1")); } }
とりあえずの例としては
大体このような流れになるかと思います。 データの扱い方はゲームによってさまざまだと思うのでそこらへんは各自応用してみてください。
参考
Google Spreadsheetに書いたシナリオをUnityのScriptableObjectにする - Qiita
Google Apps Script で spreadsheet のデータを JSON として読み込む - プログラマってこんなかんじ??
*1:ログは表示タブから開けます。