方案:

Unity的日志控制: 日志系统打开,但是只打印错误日志。这样其他级别的日志就不会有打印消耗。

UnityEngine.Debug.unityLogger.logEnabled = true;

Debug.unityLogger.filterLogType = LogType.Error;

但是还是有字符串拼接的消耗。 Conditional属性是一个C#特性,它允许你根据预处理器指令的定义来有条件地执行方法。例如下面的代码:

[Conditional("OPEN_MAIN_LOG_LOGWARNING")]

public static void Log(object message,Object context)

{

UnityEngine.Debug.Log(message,context);

}

如果没有OPEN_MAIN_LOG_LOGWARNING宏,编译的时候,所有调用Log的方法都会从Dll里去除。因此就没有了字符串拼接的消耗。

检查发现的问题:

Unity Editor下的Debug函数不应该被替换给ProjectStttings.asset文件修改宏的时候,应该全平台替换。双击日志,非ILRuntime下和ILRuntime都能跳转到对应代码的行号。注意如果ILRuntime下加了 DISABLE_ILRUNTIME_DEBUG就不会有行号的打印。

using System.IO;

using System.Reflection;

using System.Text.RegularExpressions;

using UnityEditor;

using UnityEditor.Callbacks;

using UnityEditorInternal;

using UnityEngine;

///

/// 日志重定向相关的实用函数。

///

internal static class LogRedirection

{

private static readonly Regex LogRegex = new Regex(@" \(at (.+)\:(\d+)\)\r?\n");

[OnOpenAsset(0)]

private static bool OnOpenAsset(int instanceId, int line)

{

var scriptComponent = EditorUtility.InstanceIDToObject(instanceId);

string selectedStackTrace = GetSelectedStackTrace();

if (string.IsNullOrEmpty(selectedStackTrace))

{

return false;

}

//是ILRuntime下日志

if (selectedStackTrace.Contains("ILRuntime StackTrace"))

{

//如果跳转的不是我们的GalaDebugger,证明打开的不是第一行的url,让系统跳转

if (!scriptComponent.name.Contains("GalaDebugger"))

{

return false;

}

Match match = LogRegex.Match(selectedStackTrace);

if (!match.Success)

{

return false;

}

InternalEditorUtility.OpenFileAtLineExternal(match.Groups[1].Value, int.Parse(match.Groups[2].Value));

return true;

}

else

{

//操作本质就是

//1,拿到堆栈 取得堆栈内容判断 找出正确的打开行

//2,每一个Groups实际上就是一行

//3, Groups[1]取得正好是代码路径

//4 当然自己根据实际的封装路径来搜寻正确的路径

//5,因为目前日志内容带有url属性,可以直接跳转了,因此只要跳转的路径不是默认的路径(也就是第一个路径日志),都按其系统跳转

if (!selectedStackTrace.Contains("GalaDebugger:"))

{

return false;

}

Match match = LogRegex.Match(selectedStackTrace);

if (!match.Success)

{

return false;

}

//此时找到了第一个,如果跳转的不是第一个,证明我们手动选中了其它url ---注意这里存在一个缺陷,如果选中的跳转url正好和默认路径的line一致,则会仍然跳转日志打印处

//理论上可以判断脚本的instanceId

int targetLine = int.Parse(match.Groups[2].Value);

if (targetLine != line)

{

return false;

}

if (!match.Groups[1].Value.Contains("GalaDebugger.cs"))

{

return false;

}

match = match.NextMatch();

if (!match.Success)

{

return false;

}

if (match.Groups[1].Value.Contains("GalaDebugger.cs"))

{

match = match.NextMatch();

if (!match.Success)

{

return false;

}

}

InternalEditorUtility.OpenFileAtLineExternal(

Path.Combine(Application.dataPath, match.Groups[1].Value.Substring(7)),

int.Parse(match.Groups[2].Value));

return true;

}

}

private static string GetSelectedStackTrace()

{

Assembly editorWindowAssembly = typeof(EditorWindow).Assembly;

if (editorWindowAssembly == null)

{

return null;

}

System.Type consoleWindowType = editorWindowAssembly.GetType("UnityEditor.ConsoleWindow");

if (consoleWindowType == null)

{

return null;

}

FieldInfo consoleWindowFieldInfo =

consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);

if (consoleWindowFieldInfo == null)

{

return null;

}

EditorWindow consoleWindow = consoleWindowFieldInfo.GetValue(null) as EditorWindow;

if (consoleWindow == null)

{

return null;

}

if (consoleWindow != EditorWindow.focusedWindow)

{

return null;

}

//目的就是要拿到当前选中的文本

FieldInfo activeTextFieldInfo =

consoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);

if (activeTextFieldInfo == null)

{

return null;

}

return (string)activeTextFieldInfo.GetValue(consoleWindow);

}

}

打底包和打热更的时候都应该加入Jenkins参数控制宏。增加了新的日志系统,需要显示ILRuntime的堆栈,需要加上CLR重定向。

unsafe static void CLRRedirection(ILRuntime.Runtime.Enviorment.AppDomain appdomain)

{

Type debugType = typeof(DebugEX);

var logMethod = debugType.GetMethod("Log", new[] { typeof(object) });

appdomain.RegisterCLRMethodRedirection(logMethod, Log);

var logWarningMethod = debugType.GetMethod("LogWarning", new[] { typeof(object) });

appdomain.RegisterCLRMethodRedirection(logWarningMethod, LogWarning);

var logErrorMethod = debugType.GetMethod("LogError", new[] { typeof(object) });

appdomain.RegisterCLRMethodRedirection(logErrorMethod, LogError);

}

///

/// DebugEX.Log 实现

///

///

///

///

///

///

///

unsafe static StackObject* Log(ILIntepreter __intp, StackObject* __esp, IList __mStack,

CLRMethod __method, bool isNewObj)

{

ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;

StackObject* ptr_of_this_method;

StackObject* __ret = ILIntepreter.Minus(__esp, 1);

ptr_of_this_method = ILIntepreter.Minus(__esp, 1);

object message = typeof(object).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack));

__intp.Free(ptr_of_this_method);

var stacktrace = __domain.DebugService.GetStackTrace(__intp);

DebugEX.Log(message + "\n\n==========ILRuntime StackTrace==========\n" + stacktrace);

return __ret;

}

///

/// DebugEX.LogError 实现

///

///

///

///

///

///

///

unsafe static StackObject* LogError(ILIntepreter __intp, StackObject* __esp, IList __mStack,

CLRMethod __method, bool isNewObj)

{

ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;

StackObject* ptr_of_this_method;

StackObject* __ret = ILIntepreter.Minus(__esp, 1);

ptr_of_this_method = ILIntepreter.Minus(__esp, 1);

object message = typeof(object).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack));

__intp.Free(ptr_of_this_method);

var stacktrace = __domain.DebugService.GetStackTrace(__intp);

DebugEX.LogError(message + "\n\n==========ILRuntime StackTrace==========\n" + stacktrace);

return __ret;

}

///

/// DebugEX.LogWarning 实现

///

///

///

///

///

///

///

unsafe static StackObject* LogWarning(ILIntepreter __intp, StackObject* __esp, IList __mStack,

CLRMethod __method, bool isNewObj)

{

ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;

StackObject* ptr_of_this_method;

StackObject* __ret = ILIntepreter.Minus(__esp, 1);

ptr_of_this_method = ILIntepreter.Minus(__esp, 1);

object message = typeof(object).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack));

__intp.Free(ptr_of_this_method);

var stacktrace = __domain.DebugService.GetStackTrace(__intp);

DebugEX.LogWarning(message + "\n\n==========ILRuntime StackTrace==========\n" + stacktrace);

return __ret;

}

查看原文

发表评论

返回顶部暗黑模式