在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;
}
}
版权声明:本文为suifcd原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。