Unity 实现Log实时输出到屏幕或控制台上<一>

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 

文章链接:http://blog.csdn.net/cartzhang/article/details/49818953

作者:cartzhang


一、Unity 打印日志

Unity中,在其编辑器上有个专门的Console,快捷键:shift + Ctrl+ c 。

代码中的Debug.Log("this is a test");就会打印到这里。


但是在打包后,只有从Log中找到,能不能找到一个可以实时显示的工具呢?

很明显,必须有啊!!要不写这篇不就是瞎扯了么?!!


我辗转腾挪,到处寻觅,我肯定不是第一个有这个想法的人。

终于有一天,我来到了七环!!!找到了几种方法,与君共享!!


二、我想有个控制台

之前说的Debug.Log();此函数是打印Unity控制台的。

好办,有高人已经重新把控制台给换了地方,打印到界面的控制台上。

就是类似控制台的一个界面。

先放结果图样:



1.问题来了,怎么实现的呢?

上代码:

我给改了名字叫TestConsole.cs了,因为之前名字为Console,这样想我这样都在一个工程中为大家测试,容易造成混乱。

//#define USE_TESTCONSOLE
using System.Collections.Generic;
using UnityEngine;

namespace Consolation
{
    /// <summary>
    /// A console to display Unity's debug logs in-game.
    /// </summary>
    class TestConsole : MonoBehaviour
    {
#if USE_TESTCONSOLE
        struct Log
        {
            public string message;
            public string stackTrace;
            public LogType type;
        }

        #region Inspector Settings

        /// <summary>
        /// The hotkey to show and hide the console window.
        /// </summary>
        public KeyCode toggleKey = KeyCode.BackQuote;

        /// <summary>
        /// Whether to open the window by shaking the device (mobile-only).
        /// </summary>
        public bool shakeToOpen = true;

        /// <summary>
        /// The (squared) acceleration above which the window should open.
        /// </summary>
        public float shakeAcceleration = 3f;

        /// <summary>
        /// Whether to only keep a certain number of logs.
        ///
        /// Setting this can be helpful if memory usage is a concern.
        /// </summary>
        public bool restrictLogCount = false;

        /// <summary>
        /// Number of logs to keep before removing old ones.
        /// </summary>
        public int maxLogs = 1000;

        #endregion

        readonly List<Log> logs = new List<Log>();
        Vector2 scrollPosition;
        bool visible;
        bool collapse;

        // Visual elements:

        static readonly Dictionary<LogType, Color> logTypeColors = new Dictionary<LogType, Color>
		{
			{ LogType.Assert, Color.white },
			{ LogType.Error, Color.red },
			{ LogType.Exception, Color.red },
			{ LogType.Log, Color.white },
			{ LogType.Warning, Color.yellow },
		};

        const string windowTitle = "Console";
        const int margin = 20;
        static readonly GUIContent clearLabel = new GUIContent("Clear", "Clear the contents of the console.");
        static readonly GUIContent collapseLabel = new GUIContent("Collapse", "Hide repeated messages.");

        readonly Rect titleBarRect = new Rect(0, 0, 10000, 20);
        Rect windowRect = new Rect(margin, margin, Screen.width - (margin * 2), Screen.height - (margin * 2));

        void OnEnable()
        {
#if UNITY_5
			Application.logMessageReceived += HandleLog;
#else
            Application.RegisterLogCallback(HandleLog);
#endif
        }

        void OnDisable()
        {
#if UNITY_5
			Application.logMessageReceived -= HandleLog;
#else
            Application.RegisterLogCallback(null);
#endif
        }

        void Update()
        {
            if (Input.GetKeyDown(toggleKey))
            {
                visible = !visible;
            }

            if (shakeToOpen && Input.acceleration.sqrMagnitude > shakeAcceleration)
            {
                visible = true;
            }
        }

        void OnGUI()
        {
            if (!visible)
            {
                return;
            }

            windowRect = GUILayout.Window(123456, windowRect, DrawConsoleWindow, windowTitle);
        }

        /// <summary>
        /// Displays a window that lists the recorded logs.
        /// </summary>
        /// <param name="windowID">Window ID.</param>
        void DrawConsoleWindow(int windowID)
        {
            DrawLogsList();
            DrawToolbar();

            // Allow the window to be dragged by its title bar.
            GUI.DragWindow(titleBarRect);
        }

        /// <summary>
        /// Displays a scrollable list of logs.
        /// </summary>
        void DrawLogsList()
        {
            scrollPosition = GUILayout.BeginScrollView(scrollPosition);

            // Iterate through the recorded logs.
            for (var i = 0; i < logs.Count; i++)
            {
                var log = logs[i];

                // Combine identical messages if collapse option is chosen.
                if (collapse && i > 0)
                {
                    var previousMessage = logs[i - 1].message;

                    if (log.message == previousMessage)
                    {
                        continue;
                    }
                }

                GUI.contentColor = logTypeColors[log.type];
                GUILayout.Label(log.message);
            }

            GUILayout.EndScrollView();

            // Ensure GUI colour is reset before drawing other components.
            GUI.contentColor = Color.white;
        }

        /// <summary>
        /// Displays options for filtering and changing the logs list.
        /// </summary>
        void DrawToolbar()
        {
            GUILayout.BeginHorizontal();

            if (GUILayout.Button(clearLabel))
            {
                logs.Clear();
            }

            collapse = GUILayout.Toggle(collapse, collapseLabel, GUILayout.ExpandWidth(false));

            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// Records a log from the log callback.
        /// </summary>
        /// <param name="message">Message.</param>
        /// <param name="stackTrace">Trace of where the message came from.</param>
        /// <param name="type">Type of message (error, exception, warning, assert).</param>
        void HandleLog(string message, string stackTrace, LogType type)
        {
            logs.Add(new Log
            {
                message = message,
                stackTrace = stackTrace,
                type = type,
            });

            TrimExcessLogs();
        }

        /// <summary>
        /// Removes old logs that exceed the maximum number allowed.
        /// </summary>
        void TrimExcessLogs()
        {
            if (!restrictLogCount)
            {
                return;
            }

            var amountToRemove = Mathf.Max(logs.Count - maxLogs, 0);

            if (amountToRemove == 0)
            {
                return;
            }

            logs.RemoveRange(0, amountToRemove);
        }
#endif
    }
}


我在代码最前面添加了宏定义,使用的时候屏蔽此宏定义即可

2.怎么使用呢?


恩。我写的使用很简单。
随便写个C#代码,在Update中测试的。
// Update is called once per frame
	void Update ()
    {
        //DebugConsole.Log(" test s");
        Debug.Log("Debug log  test");
        Console.WriteLine("this is Console Write line test ");
        ///
        //DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning");
        //DebugConsole.Log("this is debug console log test cartzhang");
	}

3.结果上面已经说明了。

这里就不重复了。

4.这怎么实现的呢?

原理很简单。写一个面板,往上面写字啊!

说下啊,这个有个切换按键,就是可以控制是否显示这个面板的,按键为BackQuote,你也可以修改,BackQuote这个键呢,在ESC按键的下面就是这个“~”。

三、这不是我想要的,我要显示在屏幕上。

我想要显示在控制台上,就是CMD出来的那样。

可以啊!

1. 直接写在屏幕上的代码

不过,我先赠送一个显示在屏幕上的。
这样我觉得大部分的人就会满足了,最起码不用自己写GUI .Label()了啊。

说明这个是国外友人好早之前写的,我只改变了其中某些不符合现在Unity 5 的语句,其他没有动。

还是代码:
/*==== DebugConsole.cs ====================================================
* Class for handling multi-line, multi-color debugging messages.
* Original Author: Jeremy Hollingsworth
* Based On: Version 1.2.1 Mar 02, 2006
* 
* Modified: Simon Waite
* Date: 22 Feb 2007
*
* Modification to original script to allow pixel-correct line spacing
*
* Setting the boolean pixelCorrect changes the units in lineSpacing property
* to pixels, so you have a pixel correct gui font in your console.
*
* It also checks every frame if the screen is resized to make sure the 
* line spacing is correct (To see this; drag and let go in the editor 
* and the text spacing will snap back)
*
* USAGE:
* ::Drop in your standard assets folder (if you want to change any of the
* default settings in the inspector, create an empty GameObject and attach
* this script to it from you standard assets folder.  That will provide
* access to the default settings in the inspector)
* 
* ::To use, call DebugConsole.functionOrProperty() where 
* functionOrProperty = one of the following:
* 
* -Log(string message, string color)  Adds "message" to the list with the
* "color" color. Color is optional and can be any of the following: "error",
* "warning", or "normal".  Default is normal.
* 
* Clear() Clears all messages
* 
* isVisible (true,false)  Toggles the visibility of the output.  Does _not_
* clear the messages.
* 
* isDraggable (true, false)  Toggles mouse drag functionality
* =========================================================================*/
//#define USE_DEBUGCONSOLE
 
 using UnityEngine;
 using System.Collections;


public class DebugConsole : MonoBehaviour
 {
#if USE_DEBUGCONSOLE
    public GameObject DebugGui = null;             // The GUI that will be duplicated
    public Vector3 defaultGuiPosition = new Vector3(0.01F, 0.98F, 0F);
    public Vector3 defaultGuiScale = new Vector3(0.5F, 0.5F, 1F);
    public Color normal = Color.green;
    public Color warning = Color.yellow;
    public Color error = Color.red;
    public int maxMessages = 30;                   // The max number of messages displayed
    public float lineSpacing = 0.02F;              // The amount of space between lines
    public ArrayList messages = new ArrayList();
    public ArrayList guis = new ArrayList();
    public ArrayList colors = new ArrayList();
    public bool draggable = true;                  // Can the output be dragged around at runtime by default? 
    public bool visible = true;                    // Does output show on screen by default or do we have to enable it with code? 
    public bool pixelCorrect = false; // set to be pixel Correct linespacing
    public static bool isVisible
    {                                      
        get
        {
            return DebugConsole.instance.visible;
        }
 
        set
        {
            DebugConsole.instance.visible = value;
            if (value == true)
            {
                DebugConsole.instance.Display();
            }
            else if (value == false)
            {
                DebugConsole.instance.ClearScreen();
            }
        }
    }
 
    public static bool isDraggable
    {                                      
        get
        {
            return DebugConsole.instance.draggable;
        }
 
        set
        {
            DebugConsole.instance.draggable = value;
 
        }
    }
 
 
    private static DebugConsole s_Instance = null;   // Our instance to allow this script to be called without a direct connection.
    public static DebugConsole instance
    {
        get
        {
            if (s_Instance == null)
            {
                s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
                if (s_Instance == null)
                {
                    GameObject console = new GameObject();
                    console.AddComponent<DebugConsole>();
                    console.name = "DebugConsoleController";
                    s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
                    DebugConsole.instance.InitGuis();
                }
 
            }
 
            return s_Instance;
        }
    }
 
    void Awake()
    {
        s_Instance = this;
        InitGuis();
 
    }
 
    protected bool guisCreated = false;
    protected float screenHeight =-1;
    public void InitGuis()
    {
    	float usedLineSpacing = lineSpacing;
        screenHeight = Screen.height;
        if(pixelCorrect)
            usedLineSpacing = 1.0F / screenHeight * usedLineSpacing;  
 
        if (guisCreated == false)
        {
            if (DebugGui == null)  // If an external GUIText is not set, provide the default GUIText
            {
                DebugGui = new GameObject();
                DebugGui.AddComponent<GUIText>();
                DebugGui.name = "DebugGUI(0)";
                DebugGui.transform.position = defaultGuiPosition;
                DebugGui.transform.localScale = defaultGuiScale;
            }
 
            // Create our GUI objects to our maxMessages count
            Vector3 position = DebugGui.transform.position;
            guis.Add(DebugGui);
            int x = 1;
 
            while (x < maxMessages)
            {
                position.y -= usedLineSpacing;
                GameObject clone = null;
                clone = (GameObject)Instantiate(DebugGui, position, transform.rotation);
                clone.name = string.Format("DebugGUI({0})", x);
                guis.Add(clone);
                position = clone.transform.position;
                x += 1;
            }
 
            x = 0;
            while (x < guis.Count)
            {
                GameObject temp = (GameObject)guis[x];
                temp.transform.parent = DebugGui.transform;
                x++;
            }
            guisCreated = true;
        } else {
        	// we're called on a screensize change, so fiddle with sizes
            Vector3 position = DebugGui.transform.position;
            for(int x=0;x < guis.Count; x++)
            {
                position.y -= usedLineSpacing;
            	GameObject temp = (GameObject)guis[x];
                temp.transform.position= position;
            }    	
        }
    }
 
 
 
    bool connectedToMouse = false;  
    void Update()
    {
    	// If we are visible and the screenHeight has changed, reset linespacing
    	if (visible == true && screenHeight != Screen.height)
        {
            InitGuis();
        }
        if (draggable == true)
        {
            if (Input.GetMouseButtonDown(0))
            {
                if (connectedToMouse == false && DebugGui.GetComponent<GUIText>().HitTest((Vector3)Input.mousePosition) == true)
                {
                    connectedToMouse = true;
                }
                else if (connectedToMouse == true)
                {
                    connectedToMouse = false;
                }
 
            }
 
            if (connectedToMouse == true)
            {
                float posX = DebugGui.transform.position.x;
                float posY = DebugGui.transform.position.y;
                posX = Input.mousePosition.x / Screen.width;
                posY = Input.mousePosition.y / Screen.height;
                DebugGui.transform.position = new Vector3(posX, posY, 0F);
            }
        }
 
    }
    //+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++
    public static void Log(string message, string color)
    {
        DebugConsole.instance.AddMessage(message, color);
 
    }
    //++++ OVERLOAD ++++
    public static void Log(string message)
    {
        DebugConsole.instance.AddMessage(message);
    }
 
    public static void Clear()
    {
        DebugConsole.instance.ClearMessages();
    }
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
    //---------- void AddMesage(string message, string color) ------
    //Adds a mesage to the list
    //--------------------------------------------------------------
 
    public void AddMessage(string message, string color)
    {
        messages.Add(message);
        colors.Add(color);
        Display();
    }
    //++++++++++ OVERLOAD for AddMessage ++++++++++++++++++++++++++++
    // Overloads AddMessage to only require one argument(message)
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    public void AddMessage(string message)
    {
        messages.Add(message);
        colors.Add("normal");
        Display();
    }
 
 
    //----------- void ClearMessages() ------------------------------
    // Clears the messages from the screen and the lists
    //---------------------------------------------------------------
    public void ClearMessages()
    {
        messages.Clear();
        colors.Clear();
        ClearScreen();
    }
 
 
    //-------- void ClearScreen() ----------------------------------
    // Clears all output from all GUI objects
    //--------------------------------------------------------------
    void ClearScreen()
    {
        if (guis.Count < maxMessages)
        {
            //do nothing as we haven't created our guis yet
        }
        else
        {
            int x = 0;
            while (x < guis.Count)
            {
                GameObject gui = (GameObject)guis[x];   
                gui.GetComponent<GUIText>().text = "";
                //increment and loop
                x += 1;
            }
        }
    }   
 
 
    //---------- void Prune() ---------------------------------------
    // Prunes the array to fit within the maxMessages limit
    //---------------------------------------------------------------
    void Prune()
    {
        int diff;
        if (messages.Count > maxMessages)
        {
            if (messages.Count <= 0)
            {
                diff = 0;
            }
            else
            {
                diff = messages.Count - maxMessages;
            }
            messages.RemoveRange(0, (int)diff);
            colors.RemoveRange(0, (int)diff);
        }
 
    }
 
    //---------- void Display() -------------------------------------
    // Displays the list and handles coloring
    //---------------------------------------------------------------
    void Display()
    {
        //check if we are set to display
        if (visible == false)
        {
            ClearScreen();
        }
        else if (visible == true)
        {
 
 
            if (messages.Count > maxMessages)
            {
                Prune();
            }
 
            // Carry on with display
            int x = 0;
            if (guis.Count < maxMessages)
            {
                //do nothing as we havent created our guis yet
            }
            else
            {
                while (x < messages.Count)
                {
                    GameObject gui = (GameObject)guis[x];   
 
                    //set our color
                    switch ((string)colors[x])
                    {
                        case "normal": gui.GetComponent<GUIText>().material.color = normal;
                            break;
                        case "warning": gui.GetComponent<GUIText>().material.color = warning;
                            break;
                        case "error": gui.GetComponent<GUIText>().material.color = error;
                            break;
                    }
 
                    //now set the text for this element
                    gui.GetComponent<GUIText>().text = (string)messages[x];
 
                    //increment and loop
                    x += 1;
                }
            }
 
        }
    }
#endif
 
 }// End DebugConsole Class

2.使用方法


 //DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning");
        //DebugConsole.Log("this is debug console log test cartzhang");

3.结果如图




四、这还不是我想要的,我要显示在控制台上,就是CMD出来的那样。

好吧,你赢了!!

你往下看吧!


-----------THE END ---------------

若有问题,请随时联系!
非常感谢!
--------

由于担心篇幅过长,写成下一篇吧。
再次感谢各位!


原文地址:https://www.cnblogs.com/qitian1/p/6461938.html