• 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 ---------------

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

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


  • 相关阅读:
    [算法] 网络中最小费用最大流
    [题解] 完美数
    [算法] 扫描线及其应用
    等待时间
    键盘操作
    鼠标操作
    元素常用操作
    元素的定位·CSS
    元素的定位·XPATH
    元素的定位
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461938.html
Copyright © 2020-2023  润新知