1、通过反射来查找
using System; using System.Reflection; using UnityEditor; using UnityEditor.Callbacks; using UnityEngine; internal sealed class LogIntercepter { private static LogIntercepter _current; private static LogIntercepter Current { get { if (_current == null) { _current = new LogIntercepter(); } return _current; } } private Type _consoleWindowType; private FieldInfo _activeTextInfo; private FieldInfo _consoleWindowInfo; private MethodInfo _setActiveEntry; private object[] _setActiveEntryArgs; private object _consoleWindow; private LogIntercepter() { _consoleWindowType = Type.GetType("UnityEditor.ConsoleWindow,UnityEditor"); _activeTextInfo = _consoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic); _consoleWindowInfo = _consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic); _setActiveEntry = _consoleWindowType.GetMethod("SetActiveEntry", BindingFlags.Instance | BindingFlags.NonPublic); _setActiveEntryArgs = new object[] { null }; } [OnOpenAsset] private static bool OnOpenAsset(int instanceID, int line) { UnityEngine.Object instance = EditorUtility.InstanceIDToObject(instanceID); if (AssetDatabase.GetAssetOrScenePath(instance).EndsWith(".cs")) { return Current.OpenAsset(); } return false; } private bool OpenAsset() { string stackTrace = GetStackTrace(); if (stackTrace != "") { if (stackTrace.Contains("[日志.Info]") || stackTrace.Contains("[日志.Warning]") || stackTrace.Contains("[日志.Error]")) { string[] paths = stackTrace.Split(' '); int index = 0; for (int i = 0; i < paths.Length; i++) { if (paths[i].Contains(" (at ")) { index += 1; if (index == 2) { return OpenScriptAsset(paths[i]); } } } } } return false; } private bool OpenScriptAsset(string path) { int startIndex = path.IndexOf(" (at ") + 5; int endIndex = path.IndexOf(".cs:") + 3; string filePath = path.Substring(startIndex, endIndex - startIndex); string lineStr = path.Substring(endIndex + 1, path.Length - endIndex - 2); TextAsset asset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath); if (asset != null) { int line = 0; if (int.TryParse(lineStr, out line)) { object consoleWindow = GetConsoleWindow(); _setActiveEntry.Invoke(consoleWindow, _setActiveEntryArgs); EditorGUIUtility.PingObject(asset); AssetDatabase.OpenAsset(asset, line); return true; } } return false; } private string GetStackTrace() { object consoleWindow = GetConsoleWindow(); if (consoleWindow != null) { if (consoleWindow == EditorWindow.focusedWindow as object) { object value = _activeTextInfo.GetValue(consoleWindow); return value != null ? value.ToString() : ""; } } return ""; } private object GetConsoleWindow() { if (_consoleWindow == null) { _consoleWindow = _consoleWindowInfo.GetValue(null); } return _consoleWindow; } }
2、重写Log类
using UnityEngine; /// <summary> /// 日志工具箱 /// </summary> public static class Log { private static readonly string InfoPrefix = "<b><color=cyan>[日志.Info]</color></b> "; private static readonly string WarningPrefix = "<b><color=yellow>[日志.Warning]</color></b> "; private static readonly string ErrorPrefix = "<b><color=red>[日志.Error]</color></b> "; /// <summary> /// 打印信息日志 /// </summary> /// <param name="content">日志内容</param> public static void Info(this string content) { #if UNITY_EDITOR Debug.Log(InfoPrefix + content); #else if (Main.Current.IsEnabledLogInfo) { Debug.Log(InfoPrefix + content); } #endif } /// <summary> /// 打印警告日志 /// </summary> /// <param name="content">日志内容</param> public static void Warning(this string content) { #if UNITY_EDITOR Debug.LogWarning(WarningPrefix + content); #else if (Main.Current.IsEnabledLogWarning) { Debug.LogWarning(WarningPrefix + content); } #endif } /// <summary> /// 打印错误日志 /// </summary> /// <param name="content">日志内容</param> public static void Error(this string content) { #if UNITY_EDITOR Debug.LogError(ErrorPrefix + content); #else if (Main.Current.IsEnabledLogError) { Debug.LogError(ErrorPrefix + content); } #endif } }
3、测试代码
using UnityEngine;public class NewBehaviourScript : MonoBehaviour { void Start () { Log.Info("-----"); } }
unity控制台:
双击,跳转到