プロジェクトは v2020.3 にアップグレードされ、元の v2017.3 ログ リダイレクトは利用できなくなりました。
v2017.3 ログ リダイレクト参照アドレス: https://blog.csdn.net/sufcd/article/details/72553678
理由は、UnityEditor.LogEntry と UnityEditor.LogEntries の API が変更されたためです。
直接移植すると、null エラーと Assert Failed が報告されます。
オリジナルのバージョンと比較すると、null エラーを処理するために条件フィールドがメッセージに変更され、Assert Failed の問題を処理するために StartGettingEntries と EndGettingEntries が使用されます。
コードは参考用です。直接移植しても効果がない場合があります
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using MiniJSON;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
/// <summary>
/// 日志重定向,双击调用Debugger而生成的日志,将其定位到正确的地方而不是Debugger.cs中
/// </summary>
public static class DebuggerRedirect
{
private const string LogCsName = "Debugger.cs";
private static object _logListView;
private static EditorWindow _consoleWindow;
private static MethodInfo _logEntriesGetEntry;
private static MethodInfo _logEntriesStartGettingEntries;
private static MethodInfo _logEntriesEndGettingEntries;
private static FieldInfo _logListViewCurrentRow;
private static FieldInfo _logEntryMessage;
private static object _logEntry;
private static int _openInstanceID;
private static int _openLine;
private static bool GetConsoleWindowListView()
{
if (_logListView != null) return true;
var unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow));
var consoleWindowType = unityEditorAssembly.GetType("UnityEditor.ConsoleWindow");
var fieldInfo = consoleWindowType.GetField(
"ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic
);
_consoleWindow = fieldInfo.GetValue(null) as EditorWindow;
if (_consoleWindow == null)
{
_logListView = null;
return false;
}
var listViewFieldInfo = consoleWindowType.GetField(
"m_ListView", BindingFlags.Instance | BindingFlags.NonPublic
);
_logListView = listViewFieldInfo.GetValue(_consoleWindow);
_logListViewCurrentRow = listViewFieldInfo.FieldType.GetField(
"row", BindingFlags.Instance | BindingFlags.Public
);
var logEntriesType = unityEditorAssembly.GetType("UnityEditor.LogEntries");
_logEntriesGetEntry = logEntriesType.GetMethod(
"GetEntryInternal", BindingFlags.Static | BindingFlags.Public
);
_logEntriesStartGettingEntries = logEntriesType.GetMethod(
"StartGettingEntries", BindingFlags.Static | BindingFlags.Public
);
_logEntriesEndGettingEntries = logEntriesType.GetMethod(
"EndGettingEntries", BindingFlags.Static | BindingFlags.Public
);
var logEntryType = unityEditorAssembly.GetType("UnityEditor.LogEntry");
_logEntry = Activator.CreateInstance(logEntryType);
_logEntryMessage = logEntryType.GetField("message", BindingFlags.Instance | BindingFlags.Public);
return true;
}
private static string GetListViewRowCount(ref int line)
{
var row = (int) _logListViewCurrentRow.GetValue(_logListView);
_logEntriesStartGettingEntries.Invoke(null, null);
_logEntriesGetEntry.Invoke(null, new[] {row, _logEntry});
_logEntriesEndGettingEntries.Invoke(null, null);
var message = _logEntryMessage.GetValue(_logEntry) as string;
var index = message.IndexOf(LogCsName, StringComparison.Ordinal);
if (index < 0)
return null;
var lineIndex = message.IndexOf(")", index, StringComparison.Ordinal);
message = message.Substring(lineIndex + 2);
index = message.IndexOf(".cs:", StringComparison.Ordinal);
if (index < 0)
return null;
var lineEndIndex = message.IndexOf(")", index, StringComparison.Ordinal);
var lineStr = message.Substring(index + 4, lineEndIndex - index - 4);
int.TryParse(lineStr, out line);
message = message.Substring(0, index);
var startIndex = message.LastIndexOf("/", StringComparison.Ordinal);
var fileName = message.Substring(startIndex + 1);
fileName += ".cs";
return fileName;
}
private static string IsLuaDebugger(ref int line)
{
var row = (int) _logListViewCurrentRow.GetValue(_logListView);
_logEntriesStartGettingEntries.Invoke(null, null);
_logEntriesGetEntry.Invoke(null, new[] {row, _logEntry});
_logEntriesEndGettingEntries.Invoke(null, null);
var message = _logEntryMessage.GetValue(_logEntry) as string;
if (message.Contains("print_json_start:") && message.Contains(":print_json_end"))
{
var start = message.IndexOf("print_json_start:", StringComparison.Ordinal);
var end = message.IndexOf(":print_json_end", StringComparison.Ordinal);
var filename = message.Substring(start + "print_json_start:".Length,
end - start - "print_json_start:".Length);
var dic = Json.Deserialize(filename) as Dictionary<string, object>;
line = int.Parse(dic["curLine"].ToString());
filename = dic["curSrcFile"].ToString();
return filename;
}
if (message.Contains("stack traceback:"))
{
var start = message.IndexOf("stack traceback:", StringComparison.Ordinal) +
"stack traceback:\n".Length;
var end = message.IndexOf("(...tail calls...)", StringComparison.Ordinal);
if (end == -1)
end = message.Length;
var str = message.Substring(start, end - start).Split('\n');
for (int i = 0, len = str.Length; i < len; i++)
{
var str2 = str[i].Split(':');
if (str2.Length > 2)
{
int.TryParse(str2[1], out line);
if (line > 0)
if (Regex.IsMatch(str2[0], @"^\s+[a-zA-Z0-9.]+"))
return str2[0].TrimStart('\t').TrimStart(' ');
}
}
}
var index = message.IndexOf(LogCsName, StringComparison.Ordinal);
if (index < 0)
return null;
return null;
}
[OnOpenAssetAttribute(0)]
public static bool OnOpenAsset(int instanceID, int line)
{
if (!EditorWindow.focusedWindow.titleContent.text.Equals("Console")) return false;
var openFileName = EditorUtility.InstanceIDToObject(instanceID).name;
if (!openFileName.StartsWith("Debugger"))
return false;
if (_openInstanceID == instanceID && _openLine == line)
{
_openInstanceID = -1;
_openLine = -1;
return false;
}
_openInstanceID = instanceID;
_openLine = line;
var fileName = EditorUtility.InstanceIDToObject(instanceID).name;
if (fileName != LogCsName.Substring(0, LogCsName.IndexOf(".cs", StringComparison.Ordinal)))
return false;
if (!GetConsoleWindowListView()) return false;
fileName = GetListViewRowCount(ref line) ?? IsLuaDebugger(ref line);
if (fileName == null) return false;
if (fileName.EndsWith(".cs", StringComparison.Ordinal))
{
var filter = fileName.Substring(0, fileName.Length - 3);
filter += " t:TextAsset";
var searchPaths = AssetDatabase.FindAssets(filter);
for (var i = 0; i < searchPaths.Length; i++)
{
var path = AssetDatabase.GUIDToAssetPath(searchPaths[i]);
if (fileName == Path.GetFileName(path))
{
var obj = AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset));
AssetDatabase.OpenAsset(obj, line);
return true;
}
}
}
else
{
var paths = fileName.Split('.');
fileName = paths.Aggregate("", (current, t) => current + "/" + t);
fileName += ".lua.txt";
var path = "/Lua/LuaScripts" + fileName;
if (!File.Exists(Application.dataPath + path)) path = "/Lua/Core/LuaScripts" + fileName;
var obj = AssetDatabase.LoadAssetAtPath("Assets" + path, typeof(TextAsset));
AssetDatabase.OpenAsset(obj, line);
return true;
}
return false;
}
}