Unity3D 画面上に表示出来るログ機能（レベル付き）

Qiita初投稿。
練習も兼ねて何か話題をと考えていたら、最近書いたUnity用のログクラスを思い出したので貼ってみます。
なお、Unity 4.3.4f1 での動作は確認しています。

元々は[こちら](http://d.hatena.ne.jp/nyakuo/20120429/1335717199)で紹介されていた物を見て
自分ならこんな感じに・・・と実装した物です。

## コード

```csharp:DkLog.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 画面表示可能なデバッグログ
///
/// [機能]
/// ・レベル分けログ
/// ・ログの画面表示＋色分け表示
/// ・ボタンで表示ログレベルフィルタリング
/// ・コンソールに出さないように呼び出すことも可能（コンソールログは重いので・・・）
///
/// <example>
/// // 各レベルのログ出力（コンソールにも同時に出力）
/// DkLog.V("verbose log");
/// DkLog.D("debug log");
/// DkLog.I("information log");
/// DkLog.W("warning log");
/// DkLog.E("error log");
/// 
/// // 画面にのみ出力
/// DkLog.V("verbose log (not console)", false);
/// DkLog.D("debug log (not console)", false);
/// 
/// // 画面上にログウィンドウを表示（※ OnGUI()内での呼び出しにのみ対応）
/// DkLog.DrawLogWindow(new Rect(0, Screen.Height * 0.5f, Screen.Width * 1.0f, Screen.Height * 0.5f));
/// </example>
/// </summary>

public class DkLog : MonoBehaviour
{

    #region ///////////// タイプ /////////////

    public enum Level
    {
        Verbose,
        Debug,
        Information,
        Warning,
        Error,

        Max
    }

    private struct LogData
    {
        public Level Level { get; set; }
        public string Message { get; set; }
    }

    #endregion

    #region ///////////// 定数 /////////////

    /// 表示可能ログ最大数
    private static int LOG_MAX = 200;

    /// 各レベルのログ色
    private static Color[] LOG_COLOR =
    {
        Color.gray,
        Color.white,
        Color.cyan,
        Color.yellow,
        Color.red
    };

    #endregion

    #region ///////////// メンバ /////////////
    
    private static Level _logLevel = Level.Debug;                           // 表示対象ログレベル
    private static Queue<LogData> _logQue = new Queue<LogData>(LOG_MAX);    // ログキュー
    private static Vector2 _scrollPosition = Vector2.zero;                  // スクロールビュー位置
    private static bool _isNeedScrollReset = false;                         // スクロール位置リセットフラグ
    
    #endregion

    #region ///////////// ログ処理 /////////////

    public static void V(string message, bool isConsole = true) { _Push(Level.Verbose, message, isConsole); }
    public static void D(string message, bool isConsole = true) { _Push(Level.Debug, message, isConsole); }
    public static void I(string message, bool isConsole = true) { _Push(Level.Information, message, isConsole); }
    public static void W(string message, bool isConsole = true) { _Push(Level.Warning, message, isConsole); }
    public static void E(string message, bool isConsole = true) { _Push(Level.Error, message, isConsole); }

    /// <summary>
    /// ログを画面上に表示する
    /// OnGUI() 内で呼び出して下さい
    /// </summary>
    /// <param name="drawArea">描画対象領域（左上が0,0）</param>
    public static void DrawLogWindow(Rect drawArea)
    {
        // 下地
        GUI.Box(drawArea, "");

        GUILayout.BeginArea(drawArea);
        {
            /////////////
            // ログレベル切り替えボタン
            if (GUILayout.Button(_logLevel.ToString()))
            {
                _logLevel = (Level)((int)(_logLevel + 1) % (int)Level.Max);
                _isNeedScrollReset = true;
            }

            /////////////
            // ログスクロールビュー
            _scrollPosition = GUILayout.BeginScrollView(_scrollPosition, true, true);

            int num = 0;
            GUIStyle style = new GUIStyle();
            foreach (LogData d in _logQue)
            {
                // ログレベルによって弾く
                if (d.Level >= _logLevel)
                {
                    // 0始まりのログ行数をプレフィックスとして付加しています
                    // 時刻にした方がいいかも
                    style.normal.textColor = LOG_COLOR[(int)d.Level];
                    GUILayout.Label(num.ToString() + " " + d.Message, style);                    
                    ++num;
                }
            }

            // ログ表示位置を先頭にリセットする
            if (_isNeedScrollReset)
            {
                _isNeedScrollReset = false;
                _scrollPosition.y = (num > 0) ? (num - 1) * 20 : 0;
            }

            GUILayout.EndScrollView();
        }
        GUILayout.EndArea();

    }

    /// <summary>
    /// ログをキューに詰める
    /// </summary>
    /// <param name="level"></param>
    /// <param name="message"></param>
    /// <param name="isConsole"></param>
    private static void _Push( Level level, string message, bool isConsole )
    {
        /////////////
        // キューが一杯だったら後ろを削除
        if (_logQue.Count >= LOG_MAX)
        {
            _logQue.Dequeue();
        }

        /////////////
        // キューに詰める
        LogData data = new LogData();
        {
            data.Level = level;
            data.Message = message;
        }
        _logQue.Enqueue(data);

        // ログ位置を調整する
        // @todo 出る度に勝手に動く。要らないかも？
        _isNeedScrollReset = true;

        /////////////
        // コンソール出力
        if (isConsole)
        {
            switch (level)
            {
                case Level.Warning: Debug.LogWarning(message); break;
                case Level.Error: Debug.LogError(message); break;
                default: Debug.Log(message); break;
            }
        }
    }

    #endregion
}
```

## 実行結果

画面に表示させると、以下のようになります

![UnityLog.png](https://qiita-image-store.s3.amazonaws.com/0/39914/38d44a52-59ba-e61c-d70b-30119a2dcba6.png)


Debugと書かれたボタンを押して、表示するログレベルを変更できます

![UnityLogW.png](https://qiita-image-store.s3.amazonaws.com/0/39914/272f1947-e636-3758-bfab-b7a3045dadc1.png)


## 2014/07/22 追記

[エディタよりに改修したバージョン](http://qiita.com/dk4kd/items/24dd0f4c32a170a0ec12) を投稿しました。