unity の Console ログを取得する方法は色々あると思いますが、
- 実機によって方法が異なる
- PCと実機を繋がなければいけない
などなど、いざ使おうとすると意外と面倒だったりします。
ここでは、どんな環境であろうと(たとえ PC から接続を切ったスマフォや、Switch などのコンソール機であろうと!)気楽にコンソールログを確認する方法を説明します。
簡単なところから初めて、最終的には実用に耐えるものに…?
TextMeshProUGUI にコンソールログを出す
たったこれだけのコードを TextMeshProUGUI オブジェクトにアタッチしてください。
using TMPro; using UnityEngine; public class Test1 : MonoBehaviour { TextMeshProUGUI text = null; // Start is called before the first frame update void Start() { text = GetComponent<TextMeshProUGUI>(); Application.logMessageReceived += application_logMessageReceived; } /// <summary> /// receive log /// </summary> void application_logMessageReceived(string condition, string stackTrace, LogType type) { string msg = text.text; string crlf = System.Environment.NewLine; msg += $"<color=green>{type}</color>{crlf}" + $"{condition}{crlf}" + $"<color=yellow>{stackTrace}</color>{crlf}"; text.SetText(msg); } }
表示結果
Application.logMessageReceived というイベントで、コンソールログを取得することができます。
type(緑色)がログの種類 Log、Warning、Error
condition(白色)がログ
stackTrace(黄色)が、そのログが表示された場所
簡単ですね!
ただ、これだけだと「ログが増えるほど重くなる」「最新のログが下の方にいってしまってわからない」という感じで、使い物にはならなさそうです…。
スタックトレースも必要な情報ではありますが、全部出て欲しいわけじゃないのが難しいところ。
出来るだけ簡単な方法で、これらの問題の解消を考えてみましょう。
ログが増えるほど重くなる
文字列が多くなればなるほど重くなっているので、文字数が一定量を超えたら、以前のログはカットするようにします。
残しておいても重くならない、適当なラインをアプリによって決めましょう。
今回は 1000 文字とします(ちょっと少なめ)。
ログ欲しさに重くなってたら本末転倒だし…
最新のログが下の方にいってしまってわからない
発想を逆転して「後から来たログを上に登録するように」してみましょう!
常に最下段が見えるようにする方法もありますが、実装は結構面倒です。
スタックトレースは Error だけにする
Log はトレースを追うことがほとんどない情報と割り切って、消しちゃいましょう。
Warning は悩みますが、今回は切りました。必要であればソースコードを変更してください。
ログの type も文字で表示せず、色を変えれば見た目にもわかるし、文字数も減らせそうです。
改善策を仕込んだコード
文字列を整理し、条件分岐をつけただけで、それほど大きな変更はありません。
using TMPro; using UnityEngine; public class Test1 : MonoBehaviour { TextMeshProUGUI text = null; // Start is called before the first frame update void Start() { text = GetComponent<TextMeshProUGUI>(); Application.logMessageReceived += application_logMessageReceived; } /// <summary> /// receive log /// </summary> void application_logMessageReceived(string condition, string stackTrace, LogType type) { string msg; string crlf = System.Environment.NewLine; if (type == LogType.Error) { msg = $"<color=#ee4444>{condition}{crlf}{stackTrace}</color>{crlf}"; } else if (type == LogType.Warning) { msg = $"<color=orange>{condition}</color>{crlf}{crlf}"; } else { msg = $"{condition}{crlf}{crlf}"; } msg = text.text.Insert(0, msg); if (msg.Length >= 1000) { msg = msg.Substring(0, 1000); } text.SetText(msg); } }
スタックトレースを、必要そうな情報だけにする
トレース情報って、(at Assets/Test.cs:14) のところだけわかればよかったりしますよね。
正規表現を使って、必要なテキストだけ抜き出してみましょう。
正直、正規表現はニガテだけど…
if (type == LogType.Error) { msg = $"<color=#ee4444>{condition}{crlf}{stackTrace}</color>{crlf}"; } ↓ ↓ ↓ if (type == LogType.Error) { var matches = System.Text.RegularExpressions.Regex.Matches(stackTrace, "\\(at[^\\)]+\\)"); string trace = ""; foreach (var match in matches) { trace += match + crlf; } msg = $"<color=#ee4444>{condition}{crlf}{trace}</color>{crlf}"; }
表示量が減ったので、描画も軽くなりました。
(登録時の文字列操作は重いですがログ発生の瞬間だけなので、描画を優先にした方がいいと思います)
実際のトレースログ(一番上)
New Error
UnityEngine.Debug:LogError(Object)
Test:logerror() (at Assets/Test.cs:33)
d__0:MoveNext() (at Assets/Test.cs:24)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
スクロールビューで見れるようにする
最新のログが上に表示されてはいるのですが、一度にログが登録されると、すぐ画面外にいってしまいます。これも厳しいですね。
というわけで、TextMeshProUGUI をスクロールビューの中に入れようと思います。
全然難しくないので、やってみましょう!
適当な Canvas の中に Scroll View を追加。
Content に Vertical Layout Group と Content Size Fitter を追加。
オレンジ部分の設定をデフォルトから変更してください。
Content の中に、先ほど使っていた TextMeshProUGUI を入れる。
実行すると、先ほどのログ画面がきちんとスクロールビューに収まっています。
さらに見た目をいじって、それっぽくしてみました。
以下、作業リスト。
(結構ありますが、Inspector をポチポチするだけなので時間はかかりません)
- Scroll View - Image の色を 373737 に
- Scroll View - Scroll Rect - Horizontal Scrollbar を None に(消した)
- Game Object の Scrollbar Horizontal を消す
- Scroll View > Viewport > Content - Vertical Layout Group - Padding の Left と Top を 10 に
- Scrollbar Vertical - Image のチェックを外す or 消す
- Scrollbar Vertical > Sliding Area > Handle - Image の色を 414141 に
標準機能でも十分ですが、こういう機能を自作することで開発環境のない人にもログを確認してもらうなど、用途が広がると思います。
ログをファイルに書き出すのもいいですね。色々とアレンジして、自分の使いやすいログアセットを作成してください。
私も自分カスタマイズして、例えばクリックした場所のみトレースログが出るようにしています。