Unityでオリジナルデバッグコンソールウィンドウを作ろう

ご無沙汰しております。
かれこれ前の記事が6ヶ月前という事実上の失踪と言って過言ではない状態ですが
こちらのブログは無理せずマイペースにやっていこうと思います。
とは言え、放置しすぎると戻りづらそうなので
生存報告がてら適当なものを見繕って苦し紛れに記事にしたいと思います。

デバッグログのイベントを自前でハンドルしたい方は
この記事の一番最後「自前でデバッグログイベントを拾う方法」を御覧ください。

今回の駄作

前回の記事、「uGUIのGridLayoutGroupで子要素を使い回し」で
AddStarしてくださった方がいらっしゃったので
その使い回しリストを使ってデバッグ用のログウィンドウを作ってみました。

ついでに、以前お仕事でご一緒したエンジニアさんの案だったのですが
デバッグコマンドの入力が地味に便利だったので
自分でも作ってみることにしてみました。

今回の成果物はUnityPackageで用意しました。
興味のある方は以下のリンクからダウンロードしてみてください。
UnityPackage(バイナリデータ)を表示させているのでわかりづらいかもしれませんが、
「Download」というボタンがあるので、そちらからどうぞ。
毎度のことですが、自己責任のもとであれば
勝手に改造したり使っていただいても構いません。

実装した機能

「ログの閲覧」と「デバッグコマンドの実行」の2つです。
ダウンロードしたパッケージをインポートすると
DebugConsoleフォルダの中にシーンがありますので
実行するとこんな感じのサンプルが動きます。(ログは自前で流してね)
f:id:SprField:20170926200937g:plain

 

とてもシンプルですが、デバッグコマンドを入力できる状態を作っておくと
実機でのデバッグやゲームの調整がとても楽になりますので
簡単なものでも用意しておくと後々幸せになれると思います。

デバッグコマンドの追加方法

ついでにデバッグコマンドの追加方法も軽く量産しやすく作ってみました。
もっといい方法あったかもしれませんが、ある程度簡単にしておくことで
「面倒くさくて結局やらなかった」を減らせると信じています……!
手順は2つだけ。

  • コマンドクラスの作成
  • コマンドをコンソールウィンドウに登録

だけです。
ではそれぞれの手順の説明に入ります。

 コマンドクラスの作成

ではまず、デバッグコマンド用のクラスを作ります。
ConsoleCommandBaseクラスを継承し、
コンストラクタに初期設定、ExecCommand関数にコマンドの処理を書くだけ。

▼ConsoleLog.cs

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

/// <summary>
/// コンソールコマンドサンプル
/// </summary>
public class ConsoleLog : ConsoleCommandBase
{
    /// <summary>
    /// コンストラクタ
    /// commandOverview と commandHelp は
    /// help コマンドを使用した時に表示するために用意してあります

    /// </summary>
    public ConsoleLog()
    {
        // コマンド名
        commandName = "console";
        // コマンドの概要説明文。help コマンドを実行した時に一覧に出てきます。(1行に収まる程度が好ましいです)
        commandOverview = "デバッグコマンドのサンプルです";
        // コマンドの詳細な説明文(複数行可) help console と入れた時に出てくる。
        commandHelp = "console clear\nコンソールログを全て消去します";

        // isEnableCommandをfalseにすると、入力されても処理を実行しないようにできる。
        isEnableCommand = true;
    }

    /// <summary>
    /// コマンド実行関数をオーバライド
    /// </summary>
    /// <returns>原則としてマイナス値ならエラー、0以上なら正常終了</returns>
    /// <param name="args">引数の文字列(0番目はコマンド名が入っているので注意)</param>
    public override int ExecCommand( string[] args )
    {
        if( args.Length < 1 ) {
            return -1; // 引数が足りない場合はエラー
        }

        // 書き分け方はご自由に
        switch( args[1] ) {
            // コンソールログ消去コマンド
            case "clear":
                // デバッグウィンドウはシングルトンなのでどこからでもアクセス可能
                DebugConsoleWindow.Instance.ClearConsoleLog();
                return 0;
        }
        return 0;
    }
}

コマンドをコンソールウィンドウに登録

次に、作ったクラスをコンソールウィンドウに登録します。
DebugConsoleWindow.csの157行目あたり、
EntryDebugCommand関数の中で作ったクラスを追加するだけです。

▼DebugConsoleWindow.cs(約157行目)

    /// <summary>
    /// デバッグコマンドの登録
    /// ここに ConsoleCommandBase を継承したクラスを追加していきます。
    /// </summary>
    private void EntryDebugCommand()
    {
        // ヘルプコマンドを追加
        AddDebugCommand( new HelpCommand() );
        // サンプル用のデバッグコマンドを追加
        // console clear と入力するとコンソールのログがクリアされるコマンドです
        AddDebugCommand( new ConsoleLog() );
    }

自前でデバッグログイベントを拾う方法

この記事を訪れた方の殆どは寧ろこちらがメインだと思います。
既に色々なところで紹介されていますが参考までに。
実装はとても簡単です。
Application.logMessageReceivedにイベントを追加するだけです。

void Start() {
    // コールバックの登録
    Application.logMessageReceived += LogCallBackHandler;
}

void OnDestroy() {
    // 使い終わったらコールバックを破棄
    Application.logMessageReceived -= LogCallBackHandler;
}

/// デバッグログが出力されるたびに呼ばれるコールバック
private void LogCallBackHandler( string condition, string stackTrace, LogType type )
{
    // 第一引数 condition にデバッグログの本文
    // 第ニ引数 stackTrace にはその名の通り、スタックトレースの文字列
   
    // 第三引数 type にはログタイプが入ってます。
    // ログレベルに応じて文字色を変更する時などに。
    switch( type ) {
        case LogType.Log:       /* 通常ログの場合 */    break;
        case LogType.Warning:   /* 警告ログの場合 */    break;
        case LogType.Error:     /* エラーログの場合 */   break;
        case LogType.Exception: /* 例外ログの場合 */     break;
        case LogType.Assert:    /* アサートログの場合 */ break;
    }
}

ちなみに。
古いUnityのバージョンではApplication.RegisterLogCallbackを使いますが、
現在のバージョンではObsoleteされています。

 

ということで今回はここまで。
以上、生存報告でした。