Unity实现Log实时输出到屏幕或控制台上(二)

发表于2017-11-13
评论0 1.5k浏览

一、你还是想要一个控制台来显示信息?

前面介绍了实现Log实时输出到屏幕,但是还需要一个控制台来显示信息,为什么呢?这样就不会占用Unity本身的GUI的显示,不去调用Unity的渲染,转而该为Windows的渲染了。是不是很惬意,花费少了,还更灵活了。


二、你都需要些什么?

当然是一个控制台窗口和写到控制台的输入了。

代码是歪果仁写的,但是很好用。

首先,输入的代码:
名字为ConsoleInput.cs
  1. using UnityEngine;  
  2. using System;  
  3. using System.Collections;  
  4. using System.Runtime.InteropServices;  
  5. using System.IO;  
  6.   
  7. namespace ConsoleTestWindows  
  8. {  
  9.     public class ConsoleInput  
  10.     {  
  11.         //public delegate void InputText( string strInput );  
  12.         public event System.Action<string> OnInputText;  
  13.         public string inputString;  
  14.   
  15.         public void ClearLine()  
  16.         {  
  17.             //System.Text.Encoding test = Console.InputEncoding;  
  18.             Console.CursorLeft = 0;  
  19.             Console.Write( new String( ' ', Console.BufferWidth ) );  
  20.             Console.CursorTop--;  
  21.             Console.CursorLeft = 0;  
  22.         }  
  23.   
  24.         public void RedrawInputLine()  
  25.         {  
  26.             if ( inputString.Length == 0 ) return;  
  27.   
  28.             if ( Console.CursorLeft > 0 )  
  29.                 ClearLine();  
  30.   
  31.             System.Console.ForegroundColor = ConsoleColor.Green;  
  32.             System.Console.Write( inputString );  
  33.         }  
  34.   
  35.         internal void OnBackspace()  
  36.         {  
  37.             if ( inputString.Length < 1 ) return;  
  38.   
  39.             inputString = inputString.Substring( 0, inputString.Length - 1 );  
  40.             RedrawInputLine();  
  41.         }  
  42.   
  43.         internal void OnEscape()  
  44.         {  
  45.             ClearLine();  
  46.             inputString = "";  
  47.         }  
  48.   
  49.         internal void OnEnter()  
  50.         {  
  51.             ClearLine();  
  52.             System.Console.ForegroundColor = ConsoleColor.Green;  
  53.             System.Console.WriteLine( "> " + inputString );  
  54.   
  55.             var strtext = inputString;  
  56.             inputString = "";  
  57.   
  58.             if ( OnInputText != null )  
  59.             {  
  60.                 OnInputText( strtext );  
  61.             }  
  62.         }  
  63.   
  64.         public void Update()  
  65.         {  
  66.             if ( !Console.KeyAvailable ) return;  
  67.             var key = Console.ReadKey();  
  68.   
  69.             if ( key.Key == ConsoleKey.Enter )  
  70.             {  
  71.                 OnEnter();  
  72.                 return;  
  73.             }  
  74.   
  75.             if ( key.Key == ConsoleKey.Backspace )  
  76.             {  
  77.                 OnBackspace();  
  78.                 return;  
  79.             }  
  80.   
  81.             if ( key.Key == ConsoleKey.Escape )  
  82.             {  
  83.                 OnEscape();  
  84.                 return;  
  85.             }  
  86.   
  87.             if ( key.KeyChar != '\u0000' )  
  88.             {  
  89.                 inputString += key.KeyChar;  
  90.                 RedrawInputLine();  
  91.                 return;  
  92.             }  
  93.         }  
  94.     }  
  95. }  

然后,你还需要一个控制台窗口

如下:
  1. using UnityEngine;  
  2. using System;  
  3. using System.Collections;  
  4. using System.Runtime.InteropServices;  
  5. using System.IO;  
  6.   
  7. namespace ConsoleTestWindows  
  8. {  
  9.     /// <summary>  
  10.     /// Creates a console window that actually works in Unity  
  11.     /// You should add a script that redirects output using Console.Write to write to it.  
  12.     /// </summary>  
  13.     public class ConsoleWindow  
  14.     {  
  15.         TextWriter oldOutput;  
  16.   
  17.         public void Initialize()  
  18.         {  
  19.             //  
  20.             // Attach to any existing consoles we have  
  21.             // failing that, create a new one.  
  22.             //  
  23.             if ( !AttachConsole( 0x0ffffffff ) )  
  24.             {  
  25.                 AllocConsole();  
  26.             }  
  27.   
  28.             oldOutput = Console.Out;  
  29.   
  30.             try  
  31.             {  
  32.                 IntPtr stdHandle = GetStdHandle( STD_OUTPUT_HANDLE );  
  33.                 Microsoft.Win32.SafeHandles.SafeFileHandle safeFileHandle = new Microsoft.Win32.SafeHandles.SafeFileHandle( stdHandle, true );  
  34.                 FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);  
  35.                 System.Text.Encoding encoding = System.Text.Encoding.ASCII;  
  36.                 StreamWriter standardOutput = new StreamWriter( fileStream, encoding );  
  37.                 standardOutput.AutoFlush = true;  
  38.                 Console.SetOut( standardOutput );  
  39.             }  
  40.             catch ( System.Exception e )  
  41.             {  
  42.                 Debug.Log( "Couldn't redirect output: " + e.Message );  
  43.             }  
  44.         }  
  45.   
  46.         public void Shutdown()  
  47.         {  
  48.             Console.SetOut( oldOutput );  
  49.             FreeConsole();  
  50.         }  
  51.   
  52.         public void SetTitle( string strName )  
  53.         {  
  54.             SetConsoleTitle( strName );  
  55.         }  
  56.   
  57.         private const int STD_OUTPUT_HANDLE = -11;  
  58.   
  59.         [DllImport( "kernel32.dll", SetLastError = true )]  
  60.         static extern bool AttachConsole( uint dwProcessId );  
  61.   
  62.         [DllImport( "kernel32.dll", SetLastError = true )]  
  63.         static extern bool AllocConsole();  
  64.   
  65.         [DllImport( "kernel32.dll", SetLastError = true )]  
  66.         static extern bool FreeConsole();  
  67.   
  68.         [DllImport( "kernel32.dll", EntryPoint = "GetStdHandle", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall )]  
  69.         private static extern IntPtr GetStdHandle( int nStdHandle );  
  70.   
  71.         [DllImport( "kernel32.dll" )]  
  72.         static extern bool SetConsoleTitle( string lpConsoleTitle );  
  73.     }  
  74. }  

三、输入和窗口准备齐全了,问题来了。

当你试图编译代码时候,你会发现居然编译报错,各种找不到。
Console.CursorLeft等大量的方法和变量都找不到。

这是因为Untiy5 默认的目标框架Unity3.5 .net sbu base class Libraries.。在Player Setting中,可设置为.Net 2.0。


这就可以改变了VS下的编译环境了。
但是要是你想要修改编译环境为你想要的其他呢?

四、那么问题来了?怎么修改编译环境的目标框架呢?



你肯定不会是想出这个问题的第一人?所以那就有人来解决问题;
动态的修改你的FrameWork,就可以解答这个问题。

代码:UpgradeVSProject.cs
  1. //#define USE_UPGRADEVS  
  2. using UnityEngine;  
  3. using System.Collections;  
  4. using UnityEditor;  
  5. using System.IO;  
  6. using System.Text.RegularExpressions;  
  7.   
  8. class UpgradeVSProject : AssetPostprocessor  
  9. {  
  10. #if USE_UPGRADEVS  
  11.     private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)  
  12.     {  
  13.         string currentDir = Directory.GetCurrentDirectory();  
  14.         string[] slnFile = Directory.GetFiles(currentDir, "*.sln");  
  15.         string[] csprojFile = Directory.GetFiles(currentDir, "*.csproj");  
  16.   
  17.         bool hasChanged = false;  
  18.         if (slnFile != null)  
  19.         {  
  20.             for (int i = 0; i < slnFile.Length; i++)  
  21.             {  
  22.                 if (ReplaceInFile(slnFile[i], "Format Version 10.00""Format Version 11.00"))  
  23.                     hasChanged = true;  
  24.             }  
  25.         }  
  26.   
  27.         if (csprojFile != null)  
  28.         {  
  29.             for (int i = 0; i < csprojFile.Length; i++)  
  30.             {  
  31.                 if (ReplaceInFile(csprojFile[i], "ToolsVersion=\"3.5\"""ToolsVersion=\"4.0\""))  
  32.                     hasChanged = true;  
  33.   
  34.                 if (ReplaceInFile(csprojFile[i], "<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>""<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>"))  
  35.                     hasChanged = true;  
  36.             }  
  37.         }  
  38.   
  39.         if (hasChanged)  
  40.         {  
  41.             Debug.LogWarning("Project is now upgraded to Visual Studio 2010 Solution!");  
  42.         }  
  43.         else  
  44.         {  
  45.             Debug.Log("Project-version has not changed...");  
  46.         }  
  47.     }  
  48.   
  49.     static private bool ReplaceInFile(string filePath, string searchText, string replaceText)  
  50.     {  
  51.         StreamReader reader = new StreamReader(filePath);  
  52.         string content = reader.ReadToEnd();  
  53.         reader.Close();  
  54.   
  55.         if (content.IndexOf(searchText) != -1)  
  56.         {  
  57.             content = Regex.Replace(content, searchText, replaceText);  
  58.             StreamWriter writer = new StreamWriter(filePath);  
  59.             writer.Write(content);  
  60.             writer.Close();  
  61.   
  62.             return true;  
  63.         }  
  64.   
  65.         return false;  
  66.     }  
  67. #endif  
  68. }  

同样,我写了代码屏蔽的宏定义。使用的时候启用就可以了。
就可以自动升高版本到4.0上,当然你也可以修改代码来升高到其他版本的。
注意:这个代码很明显,需要放置在Editor文件夹下。

五、测试结果

我写了个几行的测试代码:
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class Tes : MonoBehaviour {  
  5.   
  6.     // Use this for initialization  
  7.     void Start () {  
  8.       
  9.     }  
  10.       
  11.     // Update is called once per frame  
  12.     void Update ()   
  13.     {  
  14.         if (Input.GetKey(KeyCode.A))  
  15.         {  
  16.             Debug.Log("this is debug log");  
  17.             System.Console.WriteLine("this is system console write line");  
  18.         }  
  19.       
  20.     }  
  21. }  

结果就出来了:


别告诉我,这不是你想要的控制台窗口。
你看看,在写Log时,会不会造成你的游戏卡顿了呢??

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引