1. 程式人生 > >Unity控制檯日誌開啟重定向

Unity控制檯日誌開啟重定向

在Unity中,一般都會自己手動封裝一次日誌,或者自定義一些日誌輸出,比如lua程式碼的日誌輸出,雙擊開啟時我們希望重新定向的其他的檔案,而不是封裝程式碼裡,這裡要用到的主要是[OnOpenAssetAttribute(0)],每次檔案開啟時,先執行自定義的程式碼,程式碼裡自己重定向檔案和行數,然後再選擇開啟。對於Unity控制檯,我們還要用反射取得對應的日誌內容。
直接上程式碼,使用時直接修改logCSName變數,將自己封裝的日誌類寫入即可。


using System.Reflection;
using UnityEditor;
using System;
using UnityEditor.Callbacks;


public
class LogRedirect { private const string logCSName = "MyLog.cs"; private static object logListView; private static EditorWindow consoleWindow; private static FieldInfo logListViewCurrentRow; private static MethodInfo LogEntriesGetEntry; private static object logEntry; private
static FieldInfo logEntryCondition; private static int openInstanceID; private static int openLine; private static bool GetConsoleWindowListView() { if (logListView == null) { Assembly unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow)); Type consoleWindowType = unityEditorAssembly.GetType("UnityEditor.ConsoleWindow"
); FieldInfo fieldInfo = consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic); consoleWindow = fieldInfo.GetValue(null) as EditorWindow; if (consoleWindow == null) { logListView = null; return false; } FieldInfo listViewFieldInfo = consoleWindowType.GetField("m_ListView", BindingFlags.Instance | BindingFlags.NonPublic); logListView = listViewFieldInfo.GetValue(consoleWindow); logListViewCurrentRow = listViewFieldInfo.FieldType.GetField("row", BindingFlags.Instance | BindingFlags.Public); Type logEntriesType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntries"); LogEntriesGetEntry = logEntriesType.GetMethod("GetEntryInternal", BindingFlags.Static | BindingFlags.Public); Type logEntryType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntry"); logEntry = Activator.CreateInstance(logEntryType); logEntryCondition = logEntryType.GetField("condition", BindingFlags.Instance | BindingFlags.Public); } return true; } private static string GetListViewRowCount(ref int line) { int row = (int)logListViewCurrentRow.GetValue(logListView); LogEntriesGetEntry.Invoke(null, new object[] { row, logEntry }); string condition = logEntryCondition.GetValue(logEntry) as string; int index = condition.IndexOf(logCSName); if(index < 0)//不是經過我們封裝的日誌 { return null; } int lineIndex = condition.IndexOf(")", index); condition = condition.Substring(lineIndex + 2); index = condition.IndexOf(".cs:"); if (index >= 0) { int lineStartIndex = condition.IndexOf(")"); int lineEndIndex = condition.IndexOf(")", index); string _line = condition.Substring(index + 4, lineEndIndex - index - 4); Int32.TryParse(_line, out line); condition = condition.Substring(0,index); int startIndex = condition.LastIndexOf("/"); string fileName = condition.Substring(startIndex+1); fileName += ".cs"; return fileName; } return null; } [OnOpenAssetAttribute(0)] public static bool OnOpenAsset(int instanceID, int line) { if (!EditorWindow.focusedWindow.titleContent.text.Equals("Console"))//只對控制檯的開啟進行重定向 return false; //UnityEngine.Object assetObj = EditorUtility.InstanceIDToObject(instanceID); //Type assetType = assetObj.GetType(); //if(assetType != typeof(UnityEditor.MonoScript))//只對開啟的指令碼進行重定向 //{ // return false; //} if (openInstanceID == instanceID && openLine == line) { openInstanceID = -1; openLine = -1; return false; } openInstanceID = instanceID; openLine = line; if (!GetConsoleWindowListView()) { return false; } string fileName = GetListViewRowCount(ref line); if (fileName == null) { return false; } if (fileName.EndsWith(".cs")) { string filter = fileName.Substring(0, fileName.Length - 3); filter += " t:MonoScript"; string[] searchPaths = AssetDatabase.FindAssets(filter); for (int i = 0; i < searchPaths.Length; i++) { string path = AssetDatabase.GUIDToAssetPath(searchPaths[i]); if (path.EndsWith(fileName)) { UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(MonoScript)); AssetDatabase.OpenAsset(obj, line); return true; } } } return false; } }