[Unity]console中定位lua文件并在sublime中打开

    xiaoxiao2021-03-25  126

    在雨松MOMO的微博上发现可以传入lua文件路径和行数,在sublime中直接定位

    由于最近一直在写lua, 也苦于开发工具的匮乏,所以就捣鼓了一下: 下面可以看到lua代码输出的内容,双击这一条log,就根据我的配置打开sublime跳转到对应的文件以及行:

    使用方法:将下面的C#代码放到工程Editor目录下面,然后在菜单栏Tools下面有两个按钮,分别配置sublime可执行文件的路径和lua工程的根目录。

    另外需要注意的是,lua层的输出有格式规范,从上面的示例图片中可以考到,lua文件的相对路径信息在和中间,行号也在和之间。在lua层我是这么做的: 在lua执行的最开始,加入这么一段代码以替换全局的print函数,然后由外部调用该函数,会得到调用处的文件信息和行号,输出到console中,之后就会根据这些信息来定位到相应的lua文件和行。

    local tempPrint = print function print(...) local tempLog = "" for _, singleLog in ipairs({...}) do tempLog = tempLog..singleLog end tempPrint(tempLog, "<filePath>", debug.getinfo(2).short_src ,"</filePath><line>" ,debug.getinfo(2).currentline ,"</line>") end

    下面是C#代码:

    // http://blog.csdn.net/rickshaozhiheng // OpenLuaHelper.cs // Created by zhiheng.shao // Copyright 2017年 zhiheng.shao. All rights reserved. // // Description using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; using System.Reflection; using System.Text.RegularExpressions; public class OpenLuaHelper : Editor { private const string EXTERNAL_EDITOR_PATH_KEY = "mTv8"; private const string LUA_PROJECT_ROOT_FOLDER_PATH_KEY = "obUd"; //[UnityEditor.Callbacks.OnOpenAssetAttribute(0)] //static bool OnOpenAsset(int instanceID, int line) //{ // string name = EditorUtility.InstanceIDToObject(instanceID).name; // Debug.Log("Open Asset Step1,asset name=>" + name); // return true; //} [UnityEditor.Callbacks.OnOpenAssetAttribute(2)] public static bool OnOpenAsset2(int instanceID, int line) { string logText = GetLogText(); if (string.IsNullOrEmpty(logText)) return false; // get filePath Regex regex = new Regex(@"<filePath>.*<\/filePath>"); Match match = regex.Match(logText); string filePath = match.Groups[0].Value.Trim(); int length = filePath.Length - 10 - 12; filePath = filePath.Substring(10, length); filePath = filePath.Replace(".", "/"); string luaFolderRoot = EditorUserSettings.GetConfigValue(LUA_PROJECT_ROOT_FOLDER_PATH_KEY); if (string.IsNullOrEmpty(luaFolderRoot)) { SetLuaProjectRoot(); luaFolderRoot = EditorUserSettings.GetConfigValue(LUA_PROJECT_ROOT_FOLDER_PATH_KEY); } filePath = luaFolderRoot.Trim() + "/" + filePath.Trim() + ".lua"; // get line number Regex lineRegex = new Regex(@"<line>.*<\/line>"); match = lineRegex.Match(logText); string luaLineString = match.Groups[0].Value; luaLineString.Trim(); length = luaLineString.Length - 6 -11; luaLineString = luaLineString.Substring(10, length); int luaLine = int.Parse(luaLineString.Trim()); return OpenFileAtLineExternal(filePath, luaLine); } static bool OpenFileAtLineExternal(string fileName, int line) { string editorPath = EditorUserSettings.GetConfigValue(EXTERNAL_EDITOR_PATH_KEY); if (string.IsNullOrEmpty(editorPath) || !File.Exists(editorPath)) { // 没有path就弹出面板设置 SetExternalEditorPath(); } OpenFileWith(fileName, line); return true; } static void OpenFileWith(string fileName, int line) { string editorPath = EditorUserSettings.GetConfigValue(EXTERNAL_EDITOR_PATH_KEY); System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = editorPath; proc.StartInfo.Arguments = string.Format("{0}:{1}:0", fileName, line); proc.Start(); } [MenuItem("Tools/SetExternalEditorPath")] static void SetExternalEditorPath() { string path = EditorUserSettings.GetConfigValue(EXTERNAL_EDITOR_PATH_KEY); path = EditorUtility.OpenFilePanel( "SetExternalEditorPath", path, "exe"); if (path != "") { EditorUserSettings.SetConfigValue(EXTERNAL_EDITOR_PATH_KEY, path); Debug.Log("Set Editor Path: " + path); } } [MenuItem("Tools/SetLuaProjectRoot")] static void SetLuaProjectRoot() { string path = EditorUserSettings.GetConfigValue(LUA_PROJECT_ROOT_FOLDER_PATH_KEY); path = EditorUtility.OpenFolderPanel( "SetLuaProjectRoot", path, ""); if (path != "") { EditorUserSettings.SetConfigValue(LUA_PROJECT_ROOT_FOLDER_PATH_KEY, path); Debug.Log("Set Editor Path: " + path); } } static string GetLogText() { // 找到UnityEditor.EditorWindow的assembly var assembly_unity_editor = Assembly.GetAssembly(typeof(UnityEditor.EditorWindow)); if (assembly_unity_editor == null) return null; // 找到类UnityEditor.ConsoleWindow var type_console_window = assembly_unity_editor.GetType("UnityEditor.ConsoleWindow"); if (type_console_window == null) return null; // 找到UnityEditor.ConsoleWindow中的成员ms_ConsoleWindow var field_console_window = type_console_window.GetField("ms_ConsoleWindow", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); if (field_console_window == null) return null; // 获取ms_ConsoleWindow的值 var instance_console_window = field_console_window.GetValue(null); if (instance_console_window == null) return null; // 如果console窗口时焦点窗口的话,获取stacktrace if ((object)UnityEditor.EditorWindow.focusedWindow == instance_console_window) { // 通过assembly获取类ListViewState var type_list_view_state = assembly_unity_editor.GetType("UnityEditor.ListViewState"); if (type_list_view_state == null) return null; // 找到类UnityEditor.ConsoleWindow中的成员m_ListView var field_list_view = type_console_window.GetField("m_ListView", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (field_list_view == null) return null; // 获取m_ListView的值 var value_list_view = field_list_view.GetValue(instance_console_window); if (value_list_view == null) return null; // 下面是stacktrace中一些可能有用的数据、函数和使用方法,这里就不一一说明了,我们这里暂时还用不到 /* var field_row = type_list_view_state.GetField("row", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); if (field_row == null) return null; var field_total_rows = type_list_view_state.GetField("totalRows", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); if (field_total_rows == null) return null; var type_log_entries = assembly_unity_editor.GetType("UnityEditorInternal.LogEntries"); if (type_log_entries == null) return null; var method_get_entry = type_log_entries.GetMethod("GetEntryInternal", BindingFlags.Static | BindingFlags.Public); if (method_get_entry == null) return null; var type_log_entry = assembly_unity_editor.GetType("UnityEditorInternal.LogEntry"); if (type_log_entry == null) return null; var field_instance_id = type_log_entry.GetField("instanceID", BindingFlags.Instance | BindingFlags.Public); if (field_instance_id == null) return null; var field_line = type_log_entry.GetField("line", BindingFlags.Instance | BindingFlags.Public); if (field_line == null) return null; var field_condition = type_log_entry.GetField("condition", BindingFlags.Instance | BindingFlags.Public); if (field_condition == null) return null; object instance_log_entry = Activator.CreateInstance(type_log_entry); int value_row = (int)field_row.GetValue(value_list_view); int value_total_rows = (int)field_total_rows.GetValue(value_list_view); int log_by_this_count = 0; for (int i = value_total_rows – 1; i > value_row; i–) { method_get_entry.Invoke(null, new object[] { i, instance_log_entry }); string value_condition = field_condition.GetValue(instance_log_entry) as string; if (value_condition.Contains("[SDebug]")) { log_by_this_count++; } } */ // 找到类UnityEditor.ConsoleWindow中的成员m_ActiveText var field_active_text = type_console_window.GetField("m_ActiveText", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (field_active_text == null) return null; // 获得m_ActiveText的值,就是我们需要的stacktrace string value_active_text = field_active_text.GetValue(instance_console_window).ToString(); return value_active_text; } return null; } }

    参考: 1. http://weibo.com/2332920021/ExWUWBjrU?filter=hot&root_comment_id=0&type=comment#_rnd1488980161004 2. http://www.wy182000.com/2017/02/09/unity-自定义log类在编辑器中代码定位(unityeditor-callbacks-onopenassetattribute)/

    转载请注明原文地址: https://ju.6miu.com/read-7135.html

    最新回复(0)