Unity控制檯日誌開啟重定向
阿新 • • 發佈:2019-02-10
在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;
}
}