【Unity】画面にログを表示する

DEVELOP, Unity

端末単体でリアルタイムにログを確認できると結構便利。そんな訳で端末の画面上にログを表示してみます。

目次

サンプルコード

適当なGameObjectに以下のコンポーネントを追加してください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace mira
{
    /// <summary>
    /// 実機ログ表示機能。
    /// </summary>
    public class DisplayLog : MonoBehaviour
    {
        enum LogType
        {
            None,
            Log,
            Warning,
            Error,
            Assert,
            Exception,
            Num,
        };
        private const int LogStackNum = 100;
        private Queue<string> stackLog = new Queue<string>(LogStackNum);
        private BitArray logFilter = new BitArray((int)LogType.Num);
        private Vector2 scrollPosition = Vector2.zero;
        /// <summary>
        /// 開始。
        /// </summary>
        void Awake()
        {
            ClearLogFilter();
            Application.logMessageReceived += LogMessageCallBack;
        }
        /// <summary>
        /// 破棄時。
        /// </summary>
        void OnDestroy()
        {
            Application.logMessageReceived -= LogMessageCallBack;
        }
        /// <summary>
        /// 出力フィルターをクリアします。
        /// </summary>
        void ClearLogFilter()
        {
            logFilter.SetAll(false);
        }
        /// <summary>
        /// 出力フィルターを設定します。
        /// </summary>
        void SetFilter(LogType _filterMode)
        {
            logFilter.Set((int)_filterMode, true);
        }
        /// <summary>
        /// ログ通知。
        /// </summary>
        void LogMessageCallBack(string condition, string stackTrace, UnityEngine.LogType type)
        {
            string trace = null;
            string color = null;
            bool isFilter = false;
            switch (type)
            {
                case UnityEngine.LogType.Log:
                    isFilter = logFilter.Get((int)LogType.Log);
                    if (isFilter || logFilter.None())
                    {
                        trace = stackTrace.Remove(0, (stackTrace.IndexOf("\n") + 1));
                        color = "white";
                    }
                    break;
                case UnityEngine.LogType.Warning:
                    isFilter = logFilter.Get((int)LogType.Warning);
                    if (isFilter || logFilter.None())
                    {
                        trace = stackTrace.Remove(0, (stackTrace.IndexOf("\n") + 1));
                        color = "yellow";
                    }
                    break;
                case UnityEngine.LogType.Error:
                    isFilter = logFilter.Get((int)LogType.Error);
                    if (isFilter || logFilter.None())
                    {
                        trace = stackTrace.Remove(0, (stackTrace.IndexOf("\n") + 1));
                        color = "red";
                    }
                    break;
                case UnityEngine.LogType.Assert:
                    isFilter = logFilter.Get((int)LogType.Assert);
                    if (isFilter || logFilter.None())
                    {
                        trace = stackTrace.Remove(0, (stackTrace.IndexOf("\n") + 1));
                        color = "red";
                    }
                    break;
                case UnityEngine.LogType.Exception:
                    isFilter = logFilter.Get((int)LogType.Exception);
                    if (isFilter || logFilter.None())
                    {
                        trace = stackTrace;
                        color = "red";
                    }
                    break;
            }
            // ログの行制限
            if (stackLog.Count >= LogStackNum)
            {
                stackLog.Dequeue();
            }
            string message = string.Format("<color={0}>{1}</color> <color=white>on {2}</color>", color, condition, trace);
            stackLog.Enqueue(message);
        }
        /// <summary>
        /// ログのクリア。
        /// </summary>
        private void OnClearLog()
        {
            stackLog.Clear();
        }
        /// <summary>
        /// ログ表示。
        /// </summary>
        void OnGUI()
        {
            if (stackLog == null || stackLog.Count == 0)
            {
                return;
            }
            Color prevColor = GUI.backgroundColor;
            GUI.backgroundColor = new Color32(0x00, 0x00, 0x40, 0xDD);
            float scale = (Screen.width > Screen.height) ? Screen.width / 720f : Screen.height / 720f;
            GUIUtility.ScaleAroundPivot(new Vector2(scale, scale), Vector2.zero);
            var centeredStyle = new GUIStyle(GUI.skin.label);
            centeredStyle.alignment = TextAnchor.UpperCenter;
            GUILayout.BeginArea(new Rect(0, 0, Screen.width / scale, Screen.height / scale));
            GUILayout.BeginVertical(GUI.skin.box);
            {
                GUILayout.Label("DisplayLog");
                GUILayout.BeginHorizontal(GUI.skin.box);
                {
                    if (GUILayout.Button("Clear"))
                    {
                        OnClearLog();
                    }
                }
                GUILayout.EndHorizontal();
                scrollPosition = GUILayout.BeginScrollView(scrollPosition);
                foreach (string log in stackLog)
                {
                    GUILayout.Label(log);
                }
                GUILayout.EndScrollView();
            }
            GUILayout.EndVertical();
            GUILayout.EndArea();
            GUI.matrix = Matrix4x4.identity;
            GUI.backgroundColor = prevColor;
        }
    }
}

BitArrayを拡張しています。拡張内容に関してはこちらの投稿を参照してください。

テストコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
  
public class Sample: MonoBehaviour
{
    UnityEngine.LogType[] logTypes =
    {
        UnityEngine.LogType.Error,
        UnityEngine.LogType.Assert,
        UnityEngine.LogType.Warning,
        UnityEngine.LogType.Log,
        UnityEngine.LogType.Exception,
    };
 
    IEnumerator Start()
    {
        while (true)
        {
            var index = UnityEngine.Random.Range(0, logTypes.Length);
 
            switch (logTypes[index])
            {
                case UnityEngine.LogType.Error:
                    Debug.LogError("Error " + Time.time);
                    break;
                case UnityEngine.LogType.Assert:
                    Debug.Assert(false, "Assert" + Time.time);
                    break;
                case UnityEngine.LogType.Warning:
                    Debug.LogWarning("Warning " + Time.time);
                    break;
                case UnityEngine.LogType.Log:
                    Debug.Log("Log " + Time.time);
                    break;
            }
            yield return new WaitForSeconds(0.4f);
        }
    }
}

結果

画面にログを表示することができました。ログの種類によって色分けしています。

Posted by kazupon