[Unity]Debug.Logをゲーム画面上に表示し、開発を効率化

Unity
https://amzn.to/3bd8XOX

 よく、Androidの実機でゲームを動かして評価している時、ふと、ログが見たいなというケースがあります。わざわざ、PCにつないでみるのは不便だし、AndroidのADBにつないで見るのもめんどくさいし・・・今回はUnity EditorでConsoleに出力しているログをゲーム画面上に表示してみようという話です。

Goal

ゲーム画面にログウィンドウを表示する!




Scroll ViewとToggleで表示Windowを作成

 早速ScrollViewを追加していきます。追加したScrollViewはアンカーを使って画面右端に適度な幅で配置しておきます。

 Scroll ViewのContentにはLogをText形式で出力したいので、Textを追加しておきます。また、TextをスクロールするためにはContentにVertical Layout GroupとContent Size Fitter設定しておきます。詳細は以下の記事でも解説してあります。

 次にログWindow表示、非表示を切り替えるToggleを配置します。ToggleのLabelはヒエラルキーWindowのLabelで変更することができます。Toggleも同様に適当な位置にg配置しておきます。

 これで、ログ出力ONOFFとログ出力Windowの配置は完了です。

ToggleでWindowのONOFFを切り替える

 Toggleを選択してWindowのONOFFを切り替えます。ToggleのONOFFはInspectorのOn Value Changedイベントにスクリプトの関数を登録することで行います。ToggleのComponentに追加するスクリプトのサンプルは以下になります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;

public class Toggle : MonoBehaviour
{
    public GameObject DebugWindow;

    // Start と Updateは省略

    public void OnValueChanged(bool val)
    {
        // デバッグウインドウの表示切り替え
        // ToggleがONの時表示(Active)
        // ToggleがOFFの時非表示(Deactive)
        DebugWindow.SetActive(val);
    }
}

 ToggleのOn Value Changedイベントにスクリプトの関数を登録し、スクリプトのpublic変数DebugWindowにはEditorからScroll Viewを設定しておきます。

 これで一度、Toggle操作でWindowがONOFFされることを確認してみます。

Debug.Logを表示する

 続いて、Debug.Logで出力される文字列をScroll Viewに表示させていきます。Application.logMessageReceivedに関数を登録しておくと、ログ出力時に出力文字、スタックを引数に渡してコールバックしてくれる便利な機能があるので、こちらを使います。以下スクリプトのサンプルをScroll Viewに追加します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ScrollView : MonoBehaviour
{
    public GameObject DebugText;
    public GameObject DebugWindow;

    void Awake()
    {
        Application.logMessageReceived += LoggedCb;  // ログ出力時のコールバックを登録
    }

    // Start と Updateは省略

    public void LoggedCb(string logstr, string stacktrace, LogType type)
    {
        DebugText.GetComponent<Text>().text += logstr;
        DebugText.GetComponent<Text>().text += "\n";
        // 常にTextの最下部(最新)を表示するように強制スクロール
        DebugWindow.GetComponent<ScrollRect>().verticalNormalizedPosition = 0;
    }
}

 Windowいっぱいまで表示すると、自動でスクロールした方が便利なので、常にverticalNormalizedPositionを0にしてWindowの最下部を表示させるようにしています。Unity EditorからDebugTextには出力するTextとDebugWindowにはScrollViewを追加しておきます。

 後は適当にDebug.Logを実行するスクリプトを追加して、ログを出力してみます。今回はボタンに押された回数を出力するような以下のサンプルを使用してみました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Button : MonoBehaviour
{
    int _count = 0;

    // Start と Updateは省略

    public void OnClick()
    {
        _count++;
        Debug.Log("Pushed Count = "+ _count.ToString());
    }
}

 ボタンを押すたびにコンソールと同じ文字がゲーム上のWindowにも表示されることが確認できます。また、Debug Windowの表示、非表示もできています。

出力数を制限して表示を軽くする

 出力数が増えると、Textが膨大になり、処理が重くなってきて最終的には以下のエラーを出力して、ログが更新できなくなってしました。

Trying to add Text (UnityEngine.UI.Text) for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.

 ある程度(今回は200行)出力したら、古いTextは削除し、新しいテキストを追加する処理を入れておきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ScrollView : MonoBehaviour
{
    public GameObject DebugText;
    public GameObject DebugWindow;
    public int logcnt = 0;

    private Text _logText;

    void Awake()
    {
        Application.logMessageReceived += LoggedCb;  // ログ出力時のコールバックを登録
        _logText = DebugText.GetComponent<Text>();
    }

    // Start と Updateは省略

    public void LoggedCb(string logstr, string stacktrace, LogType type)
    {
        if (logcnt > 200) {
            int index = _logText.text.IndexOf("\n");
            _logText.text = _logText.text.Substring(index + 1);
        } else {
            logcnt++;
        }

        _logText.text += logstr;
        _logText.text += "\n";
        // 常にTextの最下部(最新)を表示するように強制スクロール
        DebugWindow.GetComponent<ScrollRect>().verticalNormalizedPosition = 0;
    }
}

 これでいくらログを追加しても、更新されるようになりました。Update()で毎回ログ出力すると1000くらいでエラーとなっていましたが、この対応でエラーは発生しなくなりました。

まとめ

 今回は開発時に便利なツールとしてログ出力Windowの作成方法について説明しました。ログの種類で色を変えたり、タイムスタンプを表示したり、ログのStart Stop機能を付けたりと、工夫次第で色々と使えるかと思います。

https://amzn.to/3bd8XOX

コメント

  1. […] Debug.Log をゲーム画面上に表示し、開発を効率化 | hirokuma.blog […]