UnityでのAndroidおよびiOSアプリケーションのリアルタイムデバッグ

プロジェクトがコンピューターで開発されている場合、ログを表示する問題は発生しません。 しかし、タブレットでの開発を開始すると、すべてが非常に悲しくなります。 エンジンの開発者はプロファイラーにさまざまな便利なものを追加しましたが、残念なことに彼らは単純なコンソールを忘れていました。そのため、開発者はタブに切り替えることでゲームからのメッセージを見て、コンソールコマンドをコンピューターからタブレットに直接送信できました。

現在、この省略を修正しています。



つまり、Googleドキュメントでテーブルを作成し、呼び出されたときに値を追加するスクリプトを作成します。 Debug.Log()などのコマンドをリッスンし、スクリプトに送信するスクリプトをエンジンで作成します。 10分間のケースですが、利便性が大幅に向上します。 プロジェクトにコンソールが実装されている場合、スクリプトに応答(テーブルのセルに書き込んだ内容など)を送信させることができ、これをコマンドとしてコンソールに転送できます。

すべてが非常に速く動作します。50メガビットのインターネットがあり、メッセージはほとんど瞬時に表示されます。 Googleスプレッドシート自体が更新されるため、更新する必要はありません。



まず、本質を理解するための最も簡単なオプション。



1.サーバー側のセットアップ。



サーバー側では、Googleドライブにテーブルを作成するため、Googleアカウントが必要です。



スプレッドシートを作成します。



メニューでスクリプトを作成します([ツール]-> [スクリプトエディター]-> [Webアプリとしてスクリプト])。



作成したテンプレートを削除し、次のコードをコピーします。



function doGet(e) { var sheet = SpreadsheetApp.openById("0Ap2rwVyty8rZdElOTFhlTG9BSEZGY29BZDlpQWdMR2c"); var n = sheet.getLastRow() + 1; sheet.getRange("A"+n).setValue( new Date() ); sheet.getRange("B"+n).setValue(e.parameter.p); return ContentService.createTextOutput("OK"); }
      
      







!!! コードID 0Ap2rwVyty8rZdElOTFhlTG9BSEZGY29BZDlpQWdMR2cでは、ページのIDに置き換える必要があります。作成したスプレッドシートのURLから取得できます。



このスクリプトを呼び出すと、作成したテーブルが使用され、キーpを使用してGETリクエストによって送信された時間と値が最後の行に追加されます。



RemoteLoggerなどの名前でスクリプトを保存します。



次に、バージョンを作成する必要があります([ファイル]-> [バージョンの管理]-> [新しいバージョンを保存])。



これで、次の設定で公開できます([公開]-> [Webアプリとして展開])。

!!! アプリを次のように実行します:me

!!! アプリへのアクセス権を持つユーザー:誰でも、匿名でも



[デプロイ]をクリックすると、Googleは次のようなURLを提供します。

script.google.com/macros/s/AKfycbyubkC0TQbyrRYvVD9nYezvxuDkya0Asbvff67EUK0G0oqFndws/exec

開始すると、作成したテーブルに開始時刻と未定義の値を含む行が表示されます(追加する場合)p = test at end

script.google.com/macros/s/AKfycbyubkC0TQbyrRYvVD9nYezvxuDkya0Asbvff67EUK0G0oqFndws/exec?p=test

その後、「test」という単語を含む行がテーブルに表示されます



サーバー側が正常に動作していると想定できます。



2.クライアントUnityスクリプト。



RemoteLogger.csなどのスクリプトを作成し、次のコードをそこに配置します。

 using UnityEngine; using System.Collections; using System.IO; public class RemoteLogger : MonoBehaviour { string url = "https://script.google.com/macros/s/AKfycbyubkC0TQbyrRYvVD9nYezvxuDkya0Asbvff67EUK0G0oqFndws/exec"; // Your URL copy here // Use this for initialization void Start () { Debug.Log("Hello world!"); } // Update is called once per frame void Update () { } //get method here http://forum.antichat.ru/showthread.php?t=290347 string UrlEncode(string instring) { StringReader strRdr = new StringReader(instring); StringWriter strWtr = new StringWriter(); int charValue = strRdr.Read(); while (charValue != -1) { if (((charValue >= 48) && (charValue <= 57)) // 0-9 || ((charValue >= 65) && (charValue <= 90)) // AZ || ((charValue >= 97) && (charValue <= 122))) // az { strWtr.Write((char) charValue); } else if (charValue == 32) // Space { strWtr.Write("+"); } else { strWtr.Write("%{0:x2}", charValue); } charValue = strRdr.Read(); } return strWtr.ToString(); } void SendLog(string mes) { string t_url = url + "?p=" + UrlEncode(mes); WWW www = new WWW(t_url); StartCoroutine(WaitForRequest(www)); } IEnumerator WaitForRequest(WWW www) { yield return www; // check for errors if (www.error == null) { //OK } else { //Error } } void OnEnable() { Application.RegisterLogCallback(HandleLog); } void OnDisable() { Application.RegisterLogCallback(null); } void HandleLog(string logString, string stackTrace, LogType type) { SendLog(logString); } }
      
      







!!! URLの値をスクリプトのアドレスに変更することを忘れないでください。



このスクリプトはログをリッスンし、メッセージを取得し、GETメソッドを使用して送信用にエンコードし、スクリプトに送信してテーブルに追加します。



GameObjectに追加して起動すると、ブラウザで開いているテーブルに「Hello world!」と表示されます(テーブルは自動的に更新されます)。 これが発生しなかった場合は、おそらくテーブルのID、URLを変更するのを忘れたか、スクリプトを公開するときに権限を正しく構成していません。



3.ブッチング。

プログラムに多くのメッセージがある場合、それぞれに対して新しいリクエストを作成するのは無駄です。 現在使用可能なメッセージの数に応じて、一度に最大10個のメッセージを送信します。

変更には複雑なものはないので、コードを公開して簡単に説明します。



まず、サーバー上のスクリプトを修正します。

 function doGet(e) { var sheet = SpreadsheetApp.openById("0Ap2rwVyty8rZdElOTFhlTG9BSEZGY29BZDlpQWdMR2c"); var n = sheet.getLastRow() + 1; sheet.getRange("A"+n).setValue( new Date() ); for (var j = 0; j < 10; j++) { if (e.parameter["p" + j] != null) { sheet.getRange("B"+n).setValue(e.parameter["p" + j]); n++; } } return ContentService.createTextOutput("OK"); }
      
      







つまり、p0からp9のパラメーターがソートされ、値がある場合は追加されます。



RemoteLogger.csのクラスコード

 using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; public class RemoteLogger : MonoBehaviour { string url = "https://script.google.com/macros/s/AKfycbx6q4xPM-5S7FJn1QFHHd9eXhF4yXvaguawc-yEoxU6ETFrZmU/exec"; bool sema = false; Queue<string> log = new Queue<string>(); // Use this for initialization void Awake () { DontDestroyOnLoad(gameObject); } // Use this for initialization void Start () { Debug.Log("Hello world!"); } // Update is called once per frame void Update () { if (!sema && log.Count > 0) { SendLog(); } } //get method here http://forum.antichat.ru/showthread.php?t=290347 string UrlEncode(string instring) { StringReader strRdr = new StringReader(instring); StringWriter strWtr = new StringWriter(); int charValue = strRdr.Read(); while (charValue != -1) { if (((charValue >= 48) && (charValue <= 57)) // 0-9 || ((charValue >= 65) && (charValue <= 90)) // AZ || ((charValue >= 97) && (charValue <= 122))) // az { strWtr.Write((char) charValue); } else if (charValue == 32) // Space { strWtr.Write("+"); } else { strWtr.Write("%{0:x2}", charValue); } charValue = strRdr.Read(); } return strWtr.ToString(); } void SendLog() { if (sema) return; sema = true; int count = log.Count > 10 ? 10 : log.Count; string t_url = url + "?p0=" + UrlEncode(log.Dequeue()); for (int i = 1; i < count; i++) { t_url += "&p" + i + "=" + UrlEncode(log.Dequeue()); } WWW www = new WWW(t_url); StartCoroutine(WaitForRequest(www)); } IEnumerator WaitForRequest(WWW www) { yield return www; // check for errors if (www.error == null) { //OK } else { //Error } sema = false; } void OnEnable() { Application.RegisterLogCallback(HandleLog); } void OnDisable() { Application.RegisterLogCallback(null); } void HandleLog(string logString, string stackTrace, LogType type) { log.Enqueue(logString); } }
      
      







次のシーンをロードするときにロガーが消えないようにしました。 また、ゲームにメッセージが追加され、そこから定期的に送信されるキューを追加しました。 また、セマフォを作成して、1秒間接続が多すぎないようにしました。



TODO:



必要に応じて、Unityで行われているように、エラー/警告/メッセージの種類をテーブルに渡し、それに応じて強調表示することができます。

スタックの送信元を確認することが重要な場合は、スタックを渡すことができます。

理論的には、グラフを使用できます。

フィードバックを作成し、いくつかのコマンドをゲームに転送することができます。そこでスクリプトの応答を既にリッスンし、コンソールに渡します。 簡単に追加できます。

コンソールを実行することはできませんが、「スクリーンショットを作成する」、「チートを有効にする」などのメニュー項目を追加して送信します。



一般的に、改良と拡張の機会があります。 あなたのアイデアとその実装を共有してください。誰かに役立つかもしれません。 :)



PS:サンドボックスのこの記事の著者に感謝します。



All Articles