Unity 游戲框架搭建 (九) 減少加班利器-QConsole

為毛要實現這個工具?

  1. 在我小時候,每當游戲在真機運行時,我們看到的日志是這樣的。

    沒高亮啊,還有亂七八糟的堆棧信息,好干擾日志查看,好影響心情。

  2. 還有就是必須始終連著usb線啊,我想要想躺著測試。。。 以上種種原因,QConsole誕生了。

如何使用?

使用方式和QLog一樣,在初始化出調用,簡單的一句。

QConsole.Instance();
復制代碼

就好了,使用之后效果是這樣的。

在Editor模式下,F1控制開關。

在真機上需要在屏幕上同時按下五個手指就可以控制開關了。(本來考慮11個手指萌一下的)。

實現思路:

1.首先要想辦法獲取Log,這個和上一篇介紹的QLog一樣,需要使用Application.logMessageReceived這個api。

2.獲取到的Log信息要存在一個Queue或者List中,然后把Log輸出到屏幕上就ok了。

3.輸出到屏幕上使用的是OnGUI回調和 GUILayout.Window這個api, 總共三步。

貼上代碼:

QConsole實現

sing UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections;
using System;
using System.Collections.Generic;namespace QFramework {/// <summary>/// 控制臺GUI輸出類/// 包括FPS,內存使用情況,日志GUI輸出/// </summary>public class QConsole : QSingleton<QConsole>{struct ConsoleMessage{public readonly string  message;public readonly string  stackTrace;public readonly LogType	type;public ConsoleMessage (string message, string stackTrace, LogType type){this.message    = message;this.stackTrace	= stackTrace;this.type       = type;}}/// <summary>/// Update回調/// </summary>public delegate void OnUpdateCallback();/// <summary>/// OnGUI回調/// </summary>public delegate void OnGUICallback();public OnUpdateCallback onUpdateCallback = null;public OnGUICallback onGUICallback = null;/// <summary>/// FPS計數器/// </summary>private QFPSCounter fpsCounter = null;/// <summary>/// 內存監視器/// </summary>private QMemoryDetector memoryDetector = null;private bool showGUI = true;List<ConsoleMessage> entries = new List<ConsoleMessage>();Vector2 scrollPos;bool scrollToBottom = true;bool collapse;bool mTouching = false;const int margin = 20;Rect windowRect = new Rect(margin + Screen.width * 0.5f, margin, Screen.width * 0.5f - (2 * margin), Screen.height - (2 * margin));GUIContent clearLabel    = new GUIContent("Clear",    "Clear the contents of the console.");GUIContent collapseLabel = new GUIContent("Collapse", "Hide repeated messages.");GUIContent scrollToBottomLabel = new GUIContent("ScrollToBottom", "Scroll bar always at bottom");private QConsole(){this.fpsCounter = new QFPSCounter(this);this.memoryDetector = new QMemoryDetector(this);//        this.showGUI = App.Instance().showLogOnGUI;QApp.Instance().onUpdate += Update;QApp.Instance().onGUI += OnGUI;Application.logMessageReceived += HandleLog;}~QConsole(){Application.logMessageReceived -= HandleLog;}void Update(){#if UNITY_EDITORif (Input.GetKeyUp(KeyCode.F1))this.showGUI = !this.showGUI;#elif UNITY_ANDROIDif (Input.GetKeyUp(KeyCode.Escape))this.showGUI = !this.showGUI;#elif UNITY_IOSif (!mTouching && Input.touchCount == 4){mTouching = true;this.showGUI = !this.showGUI;} else if (Input.touchCount == 0){mTouching = false;}#endifif (this.onUpdateCallback != null)this.onUpdateCallback();}void OnGUI(){if (!this.showGUI)return;if (this.onGUICallback != null)this.onGUICallback ();if (GUI.Button (new Rect (100, 100, 200, 100), "清空數據")) {PlayerPrefs.DeleteAll ();#if UNITY_EDITOREditorApplication.isPlaying = false;#elseApplication.Quit();#endif}windowRect = GUILayout.Window(123456, windowRect, ConsoleWindow, "Console");}/// <summary>/// A window displaying the logged messages./// </summary>void ConsoleWindow (int windowID){if (scrollToBottom) {GUILayout.BeginScrollView (Vector2.up * entries.Count * 100.0f);}else {scrollPos = GUILayout.BeginScrollView (scrollPos);}// Go through each logged entryfor (int i = 0; i < entries.Count; i++) {ConsoleMessage entry = entries[i];// If this message is the same as the last one and the collapse feature is chosen, skip itif (collapse && i > 0 && entry.message == entries[i - 1].message) {continue;}// Change the text colour according to the log typeswitch (entry.type) {case LogType.Error:case LogType.Exception:GUI.contentColor = Color.red;break;case LogType.Warning:GUI.contentColor = Color.yellow;break;default:GUI.contentColor = Color.white;break;}if (entry.type == LogType.Exception){GUILayout.Label(entry.message + " || " + entry.stackTrace);} else {GUILayout.Label(entry.message);}}GUI.contentColor = Color.white;GUILayout.EndScrollView();GUILayout.BeginHorizontal();// Clear buttonif (GUILayout.Button(clearLabel)) {entries.Clear();}// Collapse togglecollapse = GUILayout.Toggle(collapse, collapseLabel, GUILayout.ExpandWidth(false));scrollToBottom = GUILayout.Toggle (scrollToBottom, scrollToBottomLabel, GUILayout.ExpandWidth (false));GUILayout.EndHorizontal();// Set the window to be draggable by the top title barGUI.DragWindow(new Rect(0, 0, 10000, 20));}void HandleLog (string message, string stackTrace, LogType type){ConsoleMessage entry = new ConsoleMessage(message, stackTrace, type);entries.Add(entry);}}
}
復制代碼

QFPSCounter

using UnityEngine;
using System.Collections;namespace QFramework {/// <summary>/// 幀率計算器/// </summary>public class QFPSCounter{// 幀率計算頻率private const float calcRate = 0.5f;// 本次計算頻率下幀數private int frameCount = 0;// 頻率時長private float rateDuration = 0f;// 顯示幀率private int fps = 0;public QFPSCounter(QConsole console){console.onUpdateCallback += Update;console.onGUICallback += OnGUI;}void Start(){this.frameCount = 0;this.rateDuration = 0f;this.fps = 0;}void Update(){++this.frameCount;this.rateDuration += Time.deltaTime;if (this.rateDuration > calcRate){// 計算幀率this.fps = (int)(this.frameCount / this.rateDuration);this.frameCount = 0;this.rateDuration = 0f;}}void OnGUI(){GUI.color = Color.black;GUI.Label(new Rect(80, 20, 120, 20),"fps:" + this.fps.ToString());		}}}
復制代碼

QMemoryDetector

using UnityEngine;
using System.Collections;namespace QFramework {/// <summary>/// 內存檢測器,目前只是輸出Profiler信息/// </summary>public class QMemoryDetector {private readonly static string TotalAllocMemroyFormation = "Alloc Memory : {0}M";private readonly static string TotalReservedMemoryFormation = "Reserved Memory : {0}M";private readonly static string TotalUnusedReservedMemoryFormation = "Unused Reserved: {0}M";private readonly static string MonoHeapFormation = "Mono Heap : {0}M";private readonly static string MonoUsedFormation = "Mono Used : {0}M";// 字節到兆private float ByteToM = 0.000001f;private Rect allocMemoryRect;private Rect reservedMemoryRect;private Rect unusedReservedMemoryRect;private Rect monoHeapRect;private Rect monoUsedRect;private int x = 0;private int y = 0;private int w = 0;private int h = 0;public QMemoryDetector(QConsole console){this.x = 60;this.y = 60;this.w = 200;this.h = 20;this.allocMemoryRect = new Rect(x, y, w, h);this.reservedMemoryRect = new Rect(x, y + h, w, h);this.unusedReservedMemoryRect = new Rect(x, y + 2 * h, w, h);this.monoHeapRect = new Rect(x, y + 3 * h, w, h);this.monoUsedRect = new Rect(x, y + 4 * h, w, h);console.onGUICallback += OnGUI;}void OnGUI(){GUI.Label(this.allocMemoryRect, string.Format(TotalAllocMemroyFormation, Profiler.GetTotalAllocatedMemory() * ByteToM));GUI.Label(this.reservedMemoryRect, string.Format(TotalReservedMemoryFormation, Profiler.GetTotalReservedMemory() * ByteToM));GUI.Label(this.unusedReservedMemoryRect, string.Format(TotalUnusedReservedMemoryFormation, Profiler.GetTotalUnusedReservedMemory() * ByteToM));GUI.Label(this.monoHeapRect,string.Format(MonoHeapFormation, Profiler.GetMonoHeapSize() * ByteToM));GUI.Label(this.monoUsedRect,string.Format(MonoUsedFormation, Profiler.GetMonoUsedSize() * ByteToM));}}}
復制代碼

注意事項:

  1. 和上一篇介紹的QLog一樣,需要依賴上上篇文章介紹的QApp。

  2. QConsole初步實現來自于開源Unity插件Unity-WWW-Wrapper中的Console.cs.在此基礎上添加了ScrollToBottom選項。因為這個插件的控制臺不支持滾動顯示Log,需要拖拽右邊的scrollBar,很不方便。

  3. Unity-WWW-wrapper非常不穩定,建議大家不要使用。倒是感興趣的同學可以研究下實現,貼上地址:https://www.assetstore.unity3d.com/en/#!/content/19116。

歡迎討論!

相關鏈接:

我的框架地址:https://github.com/liangxiegame/QFramework

教程源碼:https://github.com/liangxiegame/QFramework/tree/master/Assets/HowToWriteUnityGameFramework/

QFramework&游戲框架搭建QQ交流群: 623597263

轉載請注明地址:涼鞋的筆記http://liangxiegame.com/

微信公眾號:liangxiegame

如果有幫助到您:

如果覺得本篇教程對您有幫助,不妨通過以下方式贊助筆者一下,鼓勵筆者繼續寫出更多高質量的教程,也讓更多的力量加入 QFramework 。

  • 購買 gitchat 話題《Unity 游戲框架搭建:資源管理 與 ResKit 精講》
    • 價格: 6 元,會員免費
    • 地址: http://gitbook.cn/gitchat/activity/5b29df073104f252297a779c
  • 給 QFramework 一個 Star
    • 地址: https://github.com/liangxiegame/QFramework
  • 給 Asset Store 上的 QFramework 并給個五星(需要先下載)
    • 地址: http://u3d.as/SJ9
  • 購買 gitchat 話題《Unity 游戲框架搭建:我所理解的框架》
    • 價格: 6 元,會員免費
    • 地址: http://gitbook.cn/gitchat/activity/5abc3f43bad4f418fb78ab77
  • 購買同名電子書 :https://www.kancloud.cn/liangxiegame/unity_framework_design( 29.9 元,內容會在 2018 年 10 月份完結)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282764.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282764.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282764.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android藍牙多次后,android – 如何防止BluetoothGattCallback一次多次執行

我的服務有一個BluetoothGattCallback實例public class MyService extends Service {private BluetoothGattCallback callback;Overridepublic void onCreate() {super.onCreate();callback new BluetoothGattCallback() {Overridepublic synchronized void onConnectionState…

美觀又實用,10 款強大的開源 Javascript 圖表庫

2019獨角獸企業重金招聘Python工程師標準>>> 隨著發展&#xff0c;現代 Web 設計在改善體驗和功能的同時&#xff0c;對于美觀的追求也越來越高&#xff0c;可視化、交互式、動態等元素和效果似乎已成為標配。 以下是為開發者推薦的 10 款開源 Javascript 圖表庫&am…

EF CORE 7 RC1 發布

原文鏈接&#xff1a;https://devblogs.microsoft.com/dotnet/announcing-ef7-rc1/[1]原文作者&#xff1a;Jeremy Likness翻譯&#xff1a;沙漠盡頭的狼(谷歌翻譯加持)Entity Framework Core 7 (EF7) Release Candidate 1 已發布&#xff01;該團隊專注于解決缺陷、小幅改進以…

0 重新學習Ubuntu -- 這一段沒怎么學習

在完成了前面的幾個學習后&#xff0c;再沒有進行系統的學習。 雖然在真機上安裝系統&#xff0c;每天都打開&#xff0c;完成以下的工作&#xff1a; 升級軟件用來查看相關的網站在Ubuntu上&#xff0c;現在可以完成辦公、上網、娛樂。 但專業的學習&#xff0c;例如編程方面進…

自定義地圖怎么做成html,自定義html為谷歌地圖制作標記

好吧&#xff0c;似乎Custom Overlays會做我想要的。這是ping層&#xff1a;function PingLayer(bounds, map) {this.bounds bounds;this.setMap(map);}PingLayer.prototype new google.maps.OverlayView();PingLayer.prototype.onAdd function() {var div document.create…

HDU5248:序列變換(二分)

序列變換 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1348 Accepted Submission(s): 593Problem Description給定序列A{A1,A2,...,An}, 要求改變序列A中的某些元素&#xff0c;形成一個嚴格單調的序列B&am…

微服務太分散?使用Fundebug集中式bug監控

摘要&#xff1a; 微服務日志分散&#xff0c;可以使用Fundebug的異常監控將它們集中起來。 當一個項目復雜到一定程度&#xff0c;功能越來越多&#xff0c;隨之對應的模塊也越來越多。 如果都放在一個大的項目下面&#xff0c;共同開發&#xff0c;整合發布&#xff0c;那么會…

html404頁面怎么添加,網站要如何設置自定義404頁面?

之前我們講述過網站設置404頁面對于優化或是用戶體驗的重要意義&#xff0c;大家可移步到《網站為什么要設置404頁面》查看&#xff0c;今天我們講解的是網站要如何設置自己的404頁面。現在大多數空間商都有了404設置的功能&#xff0c;我們可將404頁面上傳至空間里面&#xff…

設計模式之——工廠方法模式

1、工廠方法模式&#xff08;Factory Method&#xff09;工廠方法模式分為三種&#xff1a;11、普通工廠模式&#xff0c;就是建立一個工廠類&#xff0c;對實現了同一接口的一些類進行實例的創建。首先看下關系圖&#xff1a;舉例如下&#xff1a;&#xff08;我們舉一個發送郵…

記一次性能故障排查

最近一次公司服務出了一些性能的問題&#xff0c;主要是內存不釋放。領到任務后就開始展開工作。項目是用.net core 6寫的&#xff0c;在框上應該不會有什么問題&#xff0c;這是大背景。另外服務是部署在k8s上的&#xff0c;于是就和性能測試人員&#xff0c;開發人員搭測試環…

html單選框 點擊取消選中,radio單選框再點擊取消選中

html:html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">單選框選項a選項b選項c選項dcheckradio.js://參數&#xff1a;obj為當前點擊的radio對象function onClickRadioStyle(obj){var…

開啟AngularJS 1.X的學習之路(1)

概念(1) AngularJS 應用 AngularJS 模塊&#xff08;Module&#xff09; 定義了 AngularJS 應用。AngularJS 控制器&#xff08;Controller&#xff09; 用于控制 AngularJS 應用。ng-app指令定義了應用, ng-controller 定義了控制器。eg: <div ng-app"myApp" ng-…

Hello boke!

Hello boke&#xff01;轉載于:https://www.cnblogs.com/yikuan-919/p/9319071.html

ASP.NET Core在.NET 7 RC1中的更新

原文鏈接&#xff1a;https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-rc-1/[1]原文作者&#xff1a;Daniel Roth翻譯&#xff1a;沙漠盡頭的狼(谷歌翻譯加持).NET 7 Release Candidate 1 (RC1) 現已推出[2]&#xff0c;其中包括對 ASP.NET Core 的許…

html5 tab菜單切換頁面,11個常用的jQuery TAB切換菜單源碼及制作教程

11個常用的jQuery TAB切換菜單源碼及制作教程SponsorTAB切換式菜單可以方便為我們減少很多網頁布局空間&#xff0c;而且用jQuery的話可以加入一些動畫效果&#xff0c;比如漸變&#xff0c;向左右滑動等&#xff0c;提升一定的用戶體驗&#xff0c;所以TAB菜單目前來說是很流行…

7.16 10.19-10.22

10.19 iptables規則備份和恢復[roothyc-01-01 ~]# service iptables save 保存iptables規則該命令會將規則保存在/etc/sysconfig/iptables將iptables規則備份到一個文件中[roothyc-01-01 ~]# iptables-save>/tmp/ipt.txt將iptables規則備份到ipt.txt文件中從備份規則的文件恢…

走進javascript——不起眼的基礎,值和分號

值 有時我很想知道javascript解析引擎是如何區分一個變量的值&#xff0c;比如下面這段代碼。 var x javascript; //javascript x "hello"; // hello x 555; //555 x null; //null x a; //a is not defined x true; //true 對于數字是直接賦值的&#xff0c;因…

ConcurrentDictionary字典操作竟然不全是線程安全的?

好久不見&#xff0c;馬甲哥封閉居家半個月&#xff0c;記錄之前遇到的一件小事。ConcurrentDictionary<TKey,TValue>絕大部分api都是線程安全的[1]&#xff0c;唯二的例外是接收工廠函數的api&#xff1a;AddOrUpdate、GetOrAdd&#xff0c;這兩個api不是線程安全的&…

碼農小汪-Hibernate學習8-hibernate關聯關系注解表示@OneToMany mappedBy @ManyToMany @JoinTable...

近期我也是有點郁悶&#xff0c;究竟是程序中處理關聯關系。還是直接使用外鍵處理關聯關系呢&#xff1f;這個的說法不一致&#xff01;程序中處理這樣的關聯關系的話。自己去維護這樣的約束。這樣的非常樂觀的一種做法&#xff01;或者是直接在數據庫中處理這樣的直接的外鍵關…

HTML中彈窗中加入圖片,javascript里怎么實現點擊圖片彈出對話框?

JavaScript中可以使用document.getElementsByTagName方法后去img標簽&#xff0c;然后遍歷所有img標簽并為其添加點擊事件實現點擊彈出對話框。JavaScript實現點擊圖片彈出對話框&#xff1a;img {width: 500px;height: 300px;}//獲取所有的img標簽var imgObjs document.getEl…