Unity日誌工具——封裝,跳轉
//轉自 By D.S.Qiu
應該所有的團隊都會自己封裝日誌工具,除非引擎已經集成了,在Unity也不例外,當時之前的同事封裝了一個有一個很大不爽的地方是:從Unity ConsoleWindow 雙擊日誌跳轉到程式碼總是跳轉到封裝類中的函式,而不能直接跳轉到呼叫封裝類被呼叫的地方。
切好在準備新專案,我把原來不夠優良的地方都進行了改進直至儘可能的完美。之前一直就知道1.利用反射可以獲取Unity的private FieldInfo和 MethodInfo 可以做很多事情,2.可以利用Unity提供的api調整到指定的程式碼中去,3.Unity提供跳轉回調的機制。算是理論只是具備了,今天來公司就把這個給寫出來了,當然還對LogLevel和StackFrame資訊進行了優化(之前的有點醜,是13年一個前前同事寫的)。
其實是很簡單的,直接說下思路吧(Unity5.3):
1.記錄通過封裝日誌工具的函式呼叫棧資訊 StackFrame。
2.新增UnityEditor.Callbacks.OnOpenAssetAttribute(0)的回撥方法,處理從ConsoleWindow雙擊跳轉
3.利用反射獲取ConsoleWindow 的 ListeViewState 的 row(當前雙擊的行)和總行數
4.利用3得到行數反射獲取LogEntry資訊進行匹配獲得對應StackFrame
5.呼叫AssetDatabase.OpenAsset()即可。
更新到Unity5.3發現,他提供Logger這個類,本來還以為可以實現這些功能,不過簡單測試下來發現是不行的,我就還不清楚Unity構造一個Logger類是幹嘛的,搞得我把下面的類名改成LoggerUtility。
貼下完整的程式碼:
C#程式碼- /*
- * File: Assets/Scripts/Game/Utility/LoggerUtility.cs
- * Project: ****
- * Company: Lucky
- * Code Porter: D.S.Qiu
- * Create Date: 10/9/2015 10:11:53 PM
- */
-
using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
- #if UNITY_EDITOR
- using System.Reflection;
- using UnityEditor;
- using UnityEditor.Callbacks;
- #endif
- using UnityEngine;
- using Debug = UnityEngine.Debug;
- namespace Utility
- {
- public class LogUtility
- {
- public enum LogLevel : byte
- {
- None = 0,
- Exception = 1,
- Error = 2,
- Warning = 3,
- Info = 4,
- }
- public static LogLevel logLevel = LogLevel.Info;
- public static string infoColor = "#909090";
- public static string warningColor = "orange";
- public static string errorColor = "red";
- public static void LogBreak(object message, UnityEngine.Object sender = null)
- {
- LogInfo(message, sender);
- Debug.Break();
- }
- public static void LogFormat(string format, UnityEngine.Object sender, params object[] message)
- {
- if (logLevel >= LogLevel.Info)
- LogLevelFormat(LogLevel.Info, string.Format(format, message), sender);
- }
- public static void LogFormat(string format, params object[] message)
- {
- if (logLevel >= LogLevel.Info)
- LogLevelFormat(LogLevel.Info, string.Format(format, message), null);
- }
- public static void LogInfo(object message, UnityEngine.Object sender = null)
- {
- if(logLevel >= LogLevel.Info)
- LogLevelFormat(LogLevel.Info,message,sender);
- }
- public static void LogWarning(object message, UnityEngine.Object sender = null)
- {
- if (logLevel >= LogLevel.Warning)
- LogLevelFormat(LogLevel.Warning, message, sender);
- }
- public static void LogError(object message, UnityEngine.Object sender = null)
- {
- if (logLevel >= LogLevel.Error)
- {
- LogLevelFormat(LogLevel.Error, message, sender);
- }
- }
- public static void LogException(Exception exption, UnityEngine.Object sender = null)
- {
- if (logLevel >= LogLevel.Exception)
- {
- LogLevelFormat(LogLevel.Exception, exption, sender);
- }
- }
- private static void LogLevelFormat(LogLevel level, object message, UnityEngine.Object sender)
- {
- string levelFormat = level.ToString().ToUpper();
- StackTrace stackTrace = new StackTrace(true);
- var stackFrame = stackTrace.GetFrame(2);
- #if UNITY_EDITOR
- s_LogStackFrameList.Add(stackFrame);
- #endif
- string stackMessageFormat = Path.GetFileName(stackFrame.GetFileName()) + ":" + stackFrame.GetMethod().Name + "():at line " + stackFrame.GetFileLineNumber();
- string timeFormat = "Frame:" + Time.frameCount + "," + DateTime.Now.Millisecond + "ms";
- string objectName = string.Empty;
- string colorFormat = infoColor;
- if (level == LogLevel.Warning)
- colorFormat = warningColor;
- else if (level == LogLevel.Error)
- colorFormat = errorColor;
- StringBuilder sb = new StringBuilder();
- sb.AppendFormat("<color={3}>[{0}][{4}][{1}]{2}</color>", levelFormat, timeFormat, message, colorFormat, stackMessageFormat);
- Debug.Log(sb,sender);
- }
- #if UNITY_EDITOR
- private static int s_InstanceID;
- private static int s_Line = 104;
- private static List<StackFrame> s_LogStackFrameList = new List<StackFrame>();
- //ConsoleWindow
- private static object s_ConsoleWindow;
- private static object s_LogListView;
- private static FieldInfo s_LogListViewTotalRows;
- private static FieldInfo s_LogListViewCurrentRow;
- //LogEntry
- private static MethodInfo s_LogEntriesGetEntry;
- private static object s_LogEntry;
- //instanceId 非UnityEngine.Object的執行時 InstanceID 為零所以只能用 LogEntry.Condition 判斷
- private static FieldInfo s_LogEntryInstanceId;
- private static FieldInfo s_LogEntryLine;
- private static FieldInfo s_LogEntryCondition;
- static LogUtility()
- {
- s_InstanceID = AssetDatabase.LoadAssetAtPath<MonoScript>("Assets/Scripts/Game/Utility/LoggerUtility.cs").GetInstanceID();
- s_LogStackFrameList.Clear();
- GetConsoleWindowListView();
- }
- private static void GetConsoleWindowListView()
- {
- if (s_LogListView == null)
- {
- Assembly unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow));
- Type consoleWindowType = unityEditorAssembly.GetType("UnityEditor.ConsoleWindow");
- FieldInfo fieldInfo = consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
- s_ConsoleWindow = fieldInfo.GetValue(null);
- FieldInfo listViewFieldInfo = consoleWindowType.GetField("m_ListView", BindingFlags.Instance | BindingFlags.NonPublic);
- s_LogListView = listViewFieldInfo.GetValue(s_ConsoleWindow);
- s_LogListViewTotalRows = listViewFieldInfo.FieldType.GetField("totalRows", BindingFlags.Instance | BindingFlags.Public);
- s_LogListViewCurrentRow = listViewFieldInfo.FieldType.GetField("row", BindingFlags.Instance | BindingFlags.Public);
- //LogEntries
- Type logEntriesType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntries");
- s_LogEntriesGetEntry = logEntriesType.GetMethod("GetEntryInternal", BindingFlags.Static | BindingFlags.Public);
- Type logEntryType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntry");
- s_LogEntry = Activator.CreateInstance(logEntryType);
- s_LogEntryInstanceId = logEntryType.GetField("instanceID", BindingFlags.Instance | BindingFlags.Public);
- s_LogEntryLine = logEntryType.GetField("line", BindingFlags.Instance | BindingFlags.Public);
- s_LogEntryCondition = logEntryType.GetField("condition", BindingFlags.Instance | BindingFlags.Public);
- }
- }
- private static StackFrame GetListViewRowCount()
- {
- GetConsoleWindowListView();
- if (s_LogListView == null)
- return null;
- else
- {
- int totalRows = (int)s_LogListViewTotalRows.GetValue(s_LogListView);
- int row = (int)s_LogListViewCurrentRow.GetValue(s_LogListView);
- int logByThisClassCount = 0;
- for (int i = totalRows - 1; i >= row; i--)
- {
- s_LogEntriesGetEntry.Invoke(null, new object[] { i, s_LogEntry });
- string condition = s_LogEntryCondition.GetValue(s_LogEntry) as string;
- //判斷是否是由LoggerUtility列印的日誌
- if (condition.Contains("][") && condition.Contains("Frame"))
- logByThisClassCount++;
- }
- //同步日誌列表,ConsoleWindow 點選Clear 會清理
- while (s_LogStackFrameList.Count > totalRows)
- s_LogStackFrameList.RemoveAt(0);
- if (s_LogStackFrameList.Count >= logByThisClassCount)
- return s_LogStackFrameList[s_LogStackFrameList.Count - logByThisClassCount];
- return null;
- }
- }
- [UnityEditor.Callbacks.OnOpenAssetAttribute(0)]
- public static bool OnOpenAsset(int instanceID, int line)
- {
- if (instanceID == s_InstanceID && s_Line == line)
- {
- var stackFrame = GetListViewRowCount();
- if (stackFrame != null)
- {
- string fileName = stackFrame.GetFileName();
- string fileAssetPath = fileName.Substring(fileName.IndexOf("Assets"));
- AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath<MonoScript>(fileAssetPath), stackFrame.GetFileLineNumber());
- return true;
- }
- }
-
相關推薦
Unity日誌工具——封裝,跳轉
//轉自 By D.S.Qiu 應該所有的團隊都會自己封裝日誌工具,除非引擎已經集成了,在Unity也不例外,當時之前的同事封裝了一個有一個很大不爽的地方是:從Unity ConsoleWindow 雙擊日誌跳轉到程式碼總是跳轉到封裝類中的函式,而不能直接跳轉到呼叫封裝
4.13 apache用戶認證,跳轉和訪問日誌
用戶認證 跳轉 訪問日誌 Apache用戶認證 有的網站在訪問的時候需要我們輸入賬戶名和密碼,這樣做的好處是增加了安全性,但是用戶體驗會很差。但是在我們在工作中還需要在一些重要的地方做一些安全認證。 首先我們編輯虛擬主機的配置文件 vim /usr/local/apache2.4/conf/ext
Unity 跳轉到應用商店評價app,跳轉到Facebook某個介面,判斷手機是否安裝某個APP
private void OnGUI() { if (GUI.Button(new Rect(500, 500, 300, 150), "谷歌商店")) { openAPPinMarket(Applica
IdentityServer4 登錄成功後,跳轉到原來頁面
localhost token IdentityServer4 登錄成功後,默認會跳轉到Config.Client配置的RedirectUris地址http://localhost:5003/callback.html,用於獲取 Token,比如跳轉後的地址:http://localhost:5003
房上的貓:for循環,跳轉語句與循環結構,跳轉語句進階
必須 特點 分享 com 變量賦值 修改 表達式 判斷 條件判斷 一.for循環 1.定義: for循環語句的主要作用是反復執行一段代碼,直到滿足一定條件為止 2.組成部分: (1)初始部分:設置循環的初始狀態 (2)循環體:重復執行的代碼 (3)叠代部分:下一次循
導出excel時,跳轉新空白頁,不要跳轉怎麽改
頁面 iframe open() color one bsp pan nbsp 需要 導出excel的時候,偶爾會出現跳轉到一個新頁面再導出exceljs中用window.open()做跳轉 不想讓它跳轉到新頁面,需要加一個隱藏的iframe <iframe nam
通過js中的useragrent來判斷設備是pc端還是移動端,跳轉不同的地址
lenovo err agent indexof pad ren phi mobile 手機 if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|L
根據訪客操作系統,跳轉到不同鏈接
indexof || gpo als cati orm linu log navi 根據訪客操作系統,區分PC、wap <script> var system ={ win : false, mac : false, xll : false }; var p
js或jQuery中 郵箱跳轉的問題,跳轉到指定郵箱(通過layui的ifram實現)
按鈕 字符 新浪郵箱 實現 分享 顯示 最小化 span jquer 對剛做的東西記個筆記 如果遇到同樣問題解決起來又問題的歡迎留言 var emailtext = $("#TextBoxEmail").val();//獲得要截取的值
laravel5.4 前後臺未登陸,跳轉到各自的頁面
post eight res token fault number ssi eset www https://www.imooc.com/wenda/detail/378208?t=266634 laravel我做了前後臺登陸,後臺未登錄跳轉到前臺登陸頁面了。 我想讓後臺未
修改密碼成功後,倒計時三秒後,跳轉到登錄頁面
ESS -c win interval 將在 window com clas .html 簡單描述:需求上說,修改密碼完成之後,要有個倒計時3秒,倒計時完成之後,才返回到登錄頁面,而不是修改完密碼,立即返回到登錄的頁面 代碼: //html代碼 <div class
ci多表查詢,跳轉,訪問方式
多表查詢: $data['upvideos'] = $this->db->from('upload_video')->join('vcat', 'vcat.catid = upload_video.catid')->order_by('createtime', 'DESC')-
點選檔案,跳轉到wps瀏覽
當檔案下載完畢之後,需要進行瀏覽,有兩種方式: 1:使用TBS,即騰訊瀏覽服務,點選開啟連結 2:使用wps,由於專案受制於網路,故使用第二種方式實現,程式碼如下 public class WpsFileUtils { private static boolean isInstall
jquery點擊一組按鈕中的一個,跳轉至對應頁面處理策略。(如點擊訂單列表中的一個訂單,跳轉至該訂單的詳情)
跳轉 () 列表 操作 進行 斷點 cat 訂單 一個 將改組按鈕的數據設置一個相同的屬性(如class),然後每個按鈕設置不同的id 當用戶點擊屬性為class的按鈕,根據id屬性來判斷點擊的是哪個按鈕,然後進行相關操作。 代碼示例: <script> $("
UI_多選框,跳轉。
//跳轉 toimageview.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 彈框 Toast.makeText(MainActivity.t
hexo next主題 站內搜尋出現異常,無法正常跳轉,跳轉時出現異常
主要看看跳轉後的url是什麼,如果url異常,就需要在站點配置檔案(注意不是主題配置檔案)下面看看你的url和永久連結設定的是否正確。如下所示: # URL ## If your site is put in a subdirectory, set url as 'http://yo
關於百度推送點選通知,跳轉的問題(Android)
今天在跟同事測試百度推送,之前一直困擾我的一個問題得到了有效解決,挺高興的,所以記錄一下,同時告誡自己,遇到問題,解決解決再解決,一定能夠解決的! 切入正題,百度推送的demo跟我們的app有些不一樣
Android 應用在後臺時,跳轉 Activity 會自動切換應用至前臺
本部落格 demo 見:demo。 平常用手機的時候經常碰到這種情況,用首屏廣告舉個栗子~很多應用都會有首屏廣告 activity A,假設此應用是 app C,如果此時要使用別的應用,就會使得 app C 在後臺執行。可是當 
vue 單頁應用點擊某個鏈接,跳轉到新頁面的方式
subst ams out 詳情 targe god str blank attribute <router-link class="goDetail" :to="{name: ‘detail‘,params: {id:item.id}}" target = _bl
Android 啟動白屏,跳轉黑屏以及冷啟動優化
一,白屏 現象:啟動app,白屏一段時間後才出現歡迎頁 解決: 1,新增style <style name="AppTheme.Launcher"> <item name="android:windowDisablePreview">true<