diff --git a/UnityProject/Assets/TEngine/Editor/Utility/LogRedirection.cs b/UnityProject/Assets/TEngine/Editor/Utility/LogRedirection.cs
new file mode 100644
index 00000000..1d130e80
--- /dev/null
+++ b/UnityProject/Assets/TEngine/Editor/Utility/LogRedirection.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using UnityEditor;
+using UnityEditor.Callbacks;
+using UnityEditorInternal;
+
+namespace TEngine.Editor
+{
+ ///
+ /// 日志重定向相关的实用函数。
+ ///
+ internal static class LogRedirection
+ {
+ [OnOpenAsset(0)]
+ private static bool OnOpenAsset(int instanceID, int line)
+ {
+ if (line <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(line));
+ }
+ var stackTrace = GetStackTrace();
+ if (!string.IsNullOrEmpty(stackTrace) && (stackTrace.Contains("[Debug]") ||
+ stackTrace.Contains("[INFO]") ||
+ stackTrace.Contains("[ASSERT]") ||
+ stackTrace.Contains("[WARNING]") ||
+ stackTrace.Contains("[ERROR]") ||
+ stackTrace.Contains("[EXCEPTION]")))
+
+ {
+ // 使用正则表达式匹配at的哪个脚本的哪一行
+ var matches = Regex.Match(stackTrace, @"\(at (.+)\)",
+ RegexOptions.IgnoreCase);
+ while (matches.Success)
+ {
+ var pathLine = matches.Groups[1].Value;
+
+ if (!pathLine.Contains("Logger.cs") &&
+ !pathLine.Contains("DefaultLogHelper.cs") &&
+ !pathLine.Contains("GameFrameworkLog.cs") &&
+ !pathLine.Contains("AssetsLogger.cs") &&
+ !pathLine.Contains("Log.cs"))
+ {
+ var splitIndex = pathLine.LastIndexOf(":", StringComparison.Ordinal);
+ // 脚本路径
+ var path = pathLine.Substring(0, splitIndex);
+ // 行号
+ line = Convert.ToInt32(pathLine.Substring(splitIndex + 1));
+ var fullPath = UnityEngine.Application.dataPath.Substring(0, UnityEngine.Application.dataPath.LastIndexOf("Assets", StringComparison.Ordinal));
+ fullPath = $"{fullPath}{path}";
+ // 跳转到目标代码的特定行
+ InternalEditorUtility.OpenFileAtLineExternal(fullPath.Replace('/', '\\'), line);
+ break;
+ }
+
+ matches = matches.NextMatch();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// 获取当前日志窗口选中的日志的堆栈信息。
+ ///
+ /// 选中日志的堆栈信息实例。
+ private static string GetStackTrace()
+ {
+ // 通过反射获取ConsoleWindow类
+ var consoleWindowType = typeof(EditorWindow).Assembly.GetType("UnityEditor.ConsoleWindow");
+ // 获取窗口实例
+ var fieldInfo = consoleWindowType.GetField("ms_ConsoleWindow",
+ BindingFlags.Static |
+ BindingFlags.NonPublic);
+ if (fieldInfo != null)
+ {
+ var consoleInstance = fieldInfo.GetValue(null);
+ if (consoleInstance != null)
+ if (EditorWindow.focusedWindow == consoleInstance)
+ {
+ // 获取m_ActiveText成员
+ fieldInfo = consoleWindowType.GetField("m_ActiveText",
+ BindingFlags.Instance |
+ BindingFlags.NonPublic);
+ // 获取m_ActiveText的值
+ if (fieldInfo != null)
+ {
+ var activeText = fieldInfo.GetValue(consoleInstance).ToString();
+ return activeText;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityProject/Assets/TEngine/Editor/Utility/LogRedirection.cs.meta b/UnityProject/Assets/TEngine/Editor/Utility/LogRedirection.cs.meta
new file mode 100644
index 00000000..f7ace159
--- /dev/null
+++ b/UnityProject/Assets/TEngine/Editor/Utility/LogRedirection.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8e219db54fde57a4aae694a55da3e1b1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: