【转载】Unity编辑器扩展-ConsoleWindow中的双击日志定位

很多项目都有自己重写Debug.Log的习惯,难免会遇到在Unity的Console窗口中双击日志,但是没法直接跳转到想要看到的代码那一行的时候,解决办法有以下2种:


1、将自己封装的日志类制作成DLL再导入到Unity使用,但是有时候想修改日志类的代码却比较麻烦了~~

2、使用本文提供的LogEditor类来自动定位!。!下面来详细说明下该类吧~~


使用方法:

1、将LogEditor类的脚本放到名字为Editor的目录下(如果没有Editor目录就新建一个吧)

2、在这里修改和添加自己封装过的日志类(路径+类型),支持添加多个封装的日志类


3、现在可以直接在Console窗口中双击日志,就会自动跳转到调用自己封装日志类的代码位置啦~


附上源代码:


    
    
  1. using System;
  2. using System.Reflection;
  3. using UnityEditor;
  4. using UnityEngine;
  5. namespace shaco
  6. {
  7. public static class LogEditor
  8. {
  9. private class LogEditorConfig
  10. {
  11. public string logScriptPath = “”;
  12. public string logTypeName = “”;
  13. public int instanceID = 0;
  14. public LogEditorConfig(string logScriptPath, System.Type logType)
  15. {
  16. this.logScriptPath = logScriptPath;
  17. this.logTypeName = logType.FullName;
  18. }
  19. }
  20. //Add your custom Log class here
  21. private static LogEditorConfig[] _logEditorConfig = new LogEditorConfig[]
  22. {
  23. new LogEditorConfig( “Assets/shaco/Base/Scripts/Unity/Debug/Log.cs”, typeof(shaco.Log)),
  24. new LogEditorConfig( “Assets/shaco/Base/Scripts/CSharp/Debug/Log.cs”, typeof(shaco.Base.Log))
  25. };
  26. [ UnityEditor.Callbacks.OnOpenAssetAttribute(-1)]
  27. private static bool OnOpenAsset(int instanceID, int line)
  28. {
  29. for ( int i = _logEditorConfig.Length - 1; i >= 0; –i)
  30. {
  31. var configTmp = _logEditorConfig[i];
  32. UpdateLogInstanceID(configTmp);
  33. if (instanceID == configTmp.instanceID)
  34. {
  35. var statckTrack = GetStackTrace();
  36. if (! string.IsNullOrEmpty(statckTrack))
  37. {
  38. var fileNames = statckTrack.Split( ‘\n’);
  39. var fileName = GetCurrentFullFileName(fileNames);
  40. var fileLine = LogFileNameToFileLine(fileName);
  41. fileName = GetRealFileName(fileName);
  42. AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(fileName), fileLine);
  43. return true;
  44. }
  45. break;
  46. }
  47. }
  48. return false;
  49. }
  50. private static string GetStackTrace()
  51. {
  52. var consoleWindowType = typeof(EditorWindow).Assembly.GetType( “UnityEditor.ConsoleWindow”);
  53. var fieldInfo = consoleWindowType.GetField( “ms_ConsoleWindow”, BindingFlags.Static | BindingFlags.NonPublic);
  54. var consoleWindowInstance = fieldInfo.GetValue( null);
  55. if ( null != consoleWindowInstance)
  56. {
  57. if (( object)EditorWindow.focusedWindow == consoleWindowInstance)
  58. {
  59. // Get ListViewState in ConsoleWindow
  60. // var listViewStateType = typeof(EditorWindow).Assembly.GetType(“UnityEditor.ListViewState”);
  61. // fieldInfo = consoleWindowType.GetField(“m_ListView”, BindingFlags.Instance | BindingFlags.NonPublic);
  62. // var listView = fieldInfo.GetValue(consoleWindowInstance);
  63. // Get row in listViewState
  64. // fieldInfo = listViewStateType.GetField(“row”, BindingFlags.Instance | BindingFlags.Public);
  65. // int row = (int)fieldInfo.GetValue(listView);
  66. // Get m_ActiveText in ConsoleWindow
  67. fieldInfo = consoleWindowType.GetField( “m_ActiveText”, BindingFlags.Instance | BindingFlags.NonPublic);
  68. string activeText = fieldInfo.GetValue(consoleWindowInstance).ToString();
  69. return activeText;
  70. }
  71. }
  72. return “”;
  73. }
  74. private static void UpdateLogInstanceID(LogEditorConfig config)
  75. {
  76. if (config.instanceID > 0)
  77. {
  78. return;
  79. }
  80. var assetLoadTmp = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(config.logScriptPath);
  81. if ( null == assetLoadTmp)
  82. {
  83. throw new System.Exception( “not find asset by path=” + config.logScriptPath);
  84. }
  85. config.instanceID = assetLoadTmp.GetInstanceID();
  86. }
  87. private static string GetCurrentFullFileName(string[] fileNames)
  88. {
  89. string retValue = “”;
  90. int findIndex = -1;
  91. for ( int i = fileNames.Length - 1; i >= 0; –i)
  92. {
  93. bool isCustomLog = false;
  94. for ( int j = _logEditorConfig.Length - 1; j >= 0; –j)
  95. {
  96. if (fileNames[i].Contains(_logEditorConfig[j].logTypeName))
  97. {
  98. isCustomLog = true;
  99. break;
  100. }
  101. }
  102. if (isCustomLog)
  103. {
  104. findIndex = i;
  105. break;
  106. }
  107. }
  108. if (findIndex >= 0 && findIndex < fileNames.Length - 1)
  109. {
  110. retValue = fileNames[findIndex + 1];
  111. }
  112. return retValue;
  113. }
  114. private static string GetRealFileName(string fileName)
  115. {
  116. int indexStart = fileName.IndexOf( “(at “) + “(at “.Length;
  117. int indexEnd = ParseFileLineStartIndex(fileName) - 1;
  118. fileName = fileName.Substring(indexStart, indexEnd - indexStart);
  119. return fileName;
  120. }
  121. private static int LogFileNameToFileLine(string fileName)
  122. {
  123. int findIndex = ParseFileLineStartIndex(fileName);
  124. string stringParseLine = “”;
  125. for ( int i = findIndex; i < fileName.Length; ++i)
  126. {
  127. var charCheck = fileName[i];
  128. if (!IsNumber(charCheck))
  129. {
  130. break;
  131. }
  132. else
  133. {
  134. stringParseLine += charCheck;
  135. }
  136. }
  137. return int.Parse(stringParseLine);
  138. }
  139. private static int ParseFileLineStartIndex(string fileName)
  140. {
  141. int retValue = -1;
  142. for ( int i = fileName.Length - 1; i >= 0; –i)
  143. {
  144. var charCheck = fileName[i];
  145. bool isNumber = IsNumber(charCheck);
  146. if (isNumber)
  147. {
  148. retValue = i;
  149. }
  150. else
  151. {
  152. if (retValue != -1)
  153. {
  154. break;
  155. }
  156. }
  157. }
  158. return retValue;
  159. }
  160. private static bool IsNumber(char c)
  161. {
  162. return c >= ‘0’ && c <= ‘9’;
  163. }
  164. }
  165. }

如果感兴趣的话请多多支持下吧~~~

            </div>

很多项目都有自己重写Debug.Log的习惯,难免会遇到在Unity的Console窗口中双击日志,但是没法直接跳转到想要看到的代码那一行的时候,解决办法有以下2种:


1、将自己封装的日志类制作成DLL再导入到Unity使用,但是有时候想修改日志类的代码却比较麻烦了~~

2、使用本文提供的LogEditor类来自动定位!。!下面来详细说明下该类吧~~


使用方法:

1、将LogEditor类的脚本放到名字为Editor的目录下(如果没有Editor目录就新建一个吧)

2、在这里修改和添加自己封装过的日志类(路径+类型),支持添加多个封装的日志类


3、现在可以直接在Console窗口中双击日志,就会自动跳转到调用自己封装日志类的代码位置啦~


附上源代码:


  
  
  1. using System;
  2. using System.Reflection;
  3. using UnityEditor;
  4. using UnityEngine;
  5. namespace shaco
  6. {
  7. public static class LogEditor
  8. {
  9. private class LogEditorConfig
  10. {
  11. public string logScriptPath = “”;
  12. public string logTypeName = “”;
  13. public int instanceID = 0;
  14. public LogEditorConfig(string logScriptPath, System.Type logType)
  15. {
  16. this.logScriptPath = logScriptPath;
  17. this.logTypeName = logType.FullName;
  18. }
  19. }
  20. //Add your custom Log class here
  21. private static LogEditorConfig[] _logEditorConfig = new LogEditorConfig[]
  22. {
  23. new LogEditorConfig( “Assets/shaco/Base/Scripts/Unity/Debug/Log.cs”, typeof(shaco.Log)),
  24. new LogEditorConfig( “Assets/shaco/Base/Scripts/CSharp/Debug/Log.cs”, typeof(shaco.Base.Log))
  25. };
  26. [ UnityEditor.Callbacks.OnOpenAssetAttribute(-1)]
  27. private static bool OnOpenAsset(int instanceID, int line)
  28. {
  29. for ( int i = _logEditorConfig.Length - 1; i >= 0; –i)
  30. {
  31. var configTmp = _logEditorConfig[i];
  32. UpdateLogInstanceID(configTmp);
  33. if (instanceID == configTmp.instanceID)
  34. {
  35. var statckTrack = GetStackTrace();
  36. if (! string.IsNullOrEmpty(statckTrack))
  37. {
  38. var fileNames = statckTrack.Split( ‘\n’);
  39. var fileName = GetCurrentFullFileName(fileNames);
  40. var fileLine = LogFileNameToFileLine(fileName);
  41. fileName = GetRealFileName(fileName);
  42. AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(fileName), fileLine);
  43. return true;
  44. }
  45. break;
  46. }
  47. }
  48. return false;
  49. }
  50. private static string GetStackTrace()
  51. {
  52. var consoleWindowType = typeof(EditorWindow).Assembly.GetType( “UnityEditor.ConsoleWindow”);
  53. var fieldInfo = consoleWindowType.GetField( “ms_ConsoleWindow”, BindingFlags.Static | BindingFlags.NonPublic);
  54. var consoleWindowInstance = fieldInfo.GetValue( null);
  55. if ( null != consoleWindowInstance)
  56. {
  57. if (( object)EditorWindow.focusedWindow == consoleWindowInstance)
  58. {
  59. // Get ListViewState in ConsoleWindow
  60. // var listViewStateType = typeof(EditorWindow).Assembly.GetType(“UnityEditor.ListViewState”);
  61. // fieldInfo = consoleWindowType.GetField(“m_ListView”, BindingFlags.Instance | BindingFlags.NonPublic);
  62. // var listView = fieldInfo.GetValue(consoleWindowInstance);
  63. // Get row in listViewState
  64. // fieldInfo = listViewStateType.GetField(“row”, BindingFlags.Instance | BindingFlags.Public);
  65. // int row = (int)fieldInfo.GetValue(listView);
  66. // Get m_ActiveText in ConsoleWindow
  67. fieldInfo = consoleWindowType.GetField( “m_ActiveText”, BindingFlags.Instance | BindingFlags.NonPublic);
  68. string activeText = fieldInfo.GetValue(consoleWindowInstance).ToString();
  69. return activeText;
  70. }
  71. }
  72. return “”;
  73. }
  74. private static void UpdateLogInstanceID(LogEditorConfig config)
  75. {
  76. if (config.instanceID > 0)
  77. {
  78. return;
  79. }
  80. var assetLoadTmp = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(config.logScriptPath);
  81. if ( null == assetLoadTmp)
  82. {
  83. throw new System.Exception( “not find asset by path=” + config.logScriptPath);
  84. }
  85. config.instanceID = assetLoadTmp.GetInstanceID();
  86. }
  87. private static string GetCurrentFullFileName(string[] fileNames)
  88. {
  89. string retValue = “”;
  90. int findIndex = -1;
  91. for ( int i = fileNames.Length - 1; i >= 0; –i)
  92. {
  93. bool isCustomLog = false;
  94. for ( int j = _logEditorConfig.Length - 1; j >= 0; –j)
  95. {
  96. if (fileNames[i].Contains(_logEditorConfig[j].logTypeName))
  97. {
  98. isCustomLog = true;
  99. break;
  100. }
  101. }
  102. if (isCustomLog)
  103. {
  104. findIndex = i;
  105. break;
  106. }
  107. }
  108. if (findIndex >= 0 && findIndex < fileNames.Length - 1)
  109. {
  110. retValue = fileNames[findIndex + 1];
  111. }
  112. return retValue;
  113. }
  114. private static string GetRealFileName(string fileName)
  115. {
  116. int indexStart = fileName.IndexOf( “(at “) + “(at “.Length;
  117. int indexEnd = ParseFileLineStartIndex(fileName) - 1;
  118. fileName = fileName.Substring(indexStart, indexEnd - indexStart);
  119. return fileName;
  120. }
  121. private static int LogFileNameToFileLine(string fileName)
  122. {
  123. int findIndex = ParseFileLineStartIndex(fileName);
  124. string stringParseLine = “”;
  125. for ( int i = findIndex; i < fileName.Length; ++i)
  126. {
  127. var charCheck = fileName[i];
  128. if (!IsNumber(charCheck))
  129. {
  130. break;
  131. }
  132. else
  133. {
  134. stringParseLine += charCheck;
  135. }
  136. }
  137. return int.Parse(stringParseLine);
  138. }
  139. private static int ParseFileLineStartIndex(string fileName)
  140. {
  141. int retValue = -1;
  142. for ( int i = fileName.Length - 1; i >= 0; –i)
  143. {
  144. var charCheck = fileName[i];
  145. bool isNumber = IsNumber(charCheck);
  146. if (isNumber)
  147. {
  148. retValue = i;
  149. }
  150. else
  151. {
  152. if (retValue != -1)
  153. {
  154. break;
  155. }
  156. }
  157. }
  158. return retValue;
  159. }
  160. private static bool IsNumber(char c)
  161. {
  162. return c >= ‘0’ && c <= ‘9’;
  163. }
  164. }
  165. }

如果感兴趣的话请多多支持下吧~~~

            </div>

猜你喜欢

转载自blog.csdn.net/qq_16440237/article/details/81179272
今日推荐