众所周知,代码中使用Debug.Log*输出的日志在Unity的ConsoleWindow中可以双击定位到对应的代码行,然而将Debug.Log*封装到自己的日志类中后,定位就失去意义了。原因很简单,Unity只会处理StackFrame的栈顶信息,它们保存在LogEntry中,栈顶的方法对应的脚本文件会以其instanceID来保存,其他StackTrace信息则以字符串结果存储,最终在双击ConsoleWindow中的ListView条目时通过指定了OnOpenAssetAttribute的callback来打开代码编辑器。其中,OnOpenAssetAttribute参数用于处理存在多个Callback时的优先级问题。
通过阅读ConsoleWindow代码,想到了一个解决思路:自己实现OnOpenAsset,通过获取ConsoleWindow中的ListView得到当前选中的row,然后在LogEntries中取得该行对应的LogEntry,其中的condition字段保存了StackTrace字符串,最后过滤掉包装的日志类后拿到脚本文件名和代码行,用OpenFileAtLineExternal直接打开。在实现过程中发现,完全没有必要拿到LogEntry,因为ConsoleWindow中的m_ActiveText就是StackTrace字符串,直接处理就好了。
在想到该方案之前,看过两个解决方法:1)将日志类编译成DLL;2)输出日志时自己记录StackFrame,通过一系列手段在OnOpenAsset查找LogEntry中对应的StackFrame。不过这两种方案都不能满足个人的完美主义情节,方案1失去了预编译宏的灵活,一旦日志系统改动需要重编DLL和处理依赖,方案2低效且过于复杂。
最后摘出代码供参考,实现环境为:Unity 4.7.5f1, UnityVS+Visual Studio 2015 Pro。