在Unity編輯器下能夠查看log輸出、內存信息、系統信息等,但發佈到移動端不少信息都沒法查看,這個自定義的調試器能夠查看一些遊戲信息,方便調試
編輯器
——在遊戲啓動時調用Debugger.Ins.OpenDebugger()開啓調試器ide
using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Profiling; /// <summary> /// 調試器 /// </summary> public class Debugger : MonoBehaviour { private static Debugger _instance; public static Debugger Ins { get { if (_instance == null) { var go = new GameObject(typeof(Debugger).ToString()); GameObject.DontDestroyOnLoad(go); _instance = go.AddComponent<Debugger>(); } return _instance; } } bool showDebugger;//是否顯示調試器 int windowTypeIndex;//窗口類型下標 //窗口類型字符串 string[] debuggerTypeStr = new string[] { "Log", //Log "Memory", //內存 "Screen", //屏幕 "System", //系統 "Environment"//環境 }; GUIStyle titleStyle;//標題樣式 GUIStyle logStyle_selected;//log被選擇的樣式 GUIStyle logStyle_info;//log樣式(info) GUIStyle logStyle_warning;//log樣式(warning) GUIStyle logStyle_error;//log樣式(error) GUIStyle stackStyle;//堆棧樣式 /// <summary> /// 打開調試器 /// </summary> public void OpenDebugger() { } public void Awake() { InitStyle(); Application.logMessageReceived += LogCallBack; } private void OnDestroy() { Application.logMessageReceived -= LogCallBack; } /// <summary> /// 初始化樣式 /// </summary> void InitStyle() { titleStyle = new GUIStyle(); titleStyle.fontSize = 30; titleStyle.fontStyle = FontStyle.Bold; titleStyle.alignment = TextAnchor.MiddleCenter; titleStyle.normal.textColor = Color.cyan; logStyle_selected = new GUIStyle(); logStyle_selected.fontSize = 24; logStyle_selected.normal.textColor = Color.cyan; logStyle_info = new GUIStyle(); logStyle_info.fontSize = 24; logStyle_info.normal.textColor = Color.white; logStyle_warning = new GUIStyle(); logStyle_warning.fontSize = 24; logStyle_warning.normal.textColor = Color.yellow; logStyle_error = new GUIStyle(); logStyle_error.fontSize = 24; logStyle_error.normal.textColor = Color.red; stackStyle = new GUIStyle(); stackStyle.fontSize = 24; } private void OnGUI() { if (showDebugger) { DrawDebugger(); } else { if (GUILayout.Button("調試器", GUILayout.Width(100), GUILayout.Height(100))) { showDebugger = true; } } } /// <summary> /// 繪製調試器 /// </summary> void DrawDebugger() { GUILayout.BeginVertical("box", GUILayout.MinWidth(Screen.width)); GUILayout.Label("調試器", titleStyle); GUILayout.BeginVertical("box"); windowTypeIndex = GUILayout.Toolbar(windowTypeIndex, debuggerTypeStr, GUILayout.MinWidth(Screen.width / 10), GUILayout.MinHeight(Screen.height / 20)); if (windowTypeIndex == 0) { //繪製Log窗口 DrawLogWindow(); } else if (windowTypeIndex == 1) { //繪製內存窗口 DrawMemoryWindow(); } else if (windowTypeIndex == 2) { //繪製屏幕窗口 DrawScreenWindow(); } else if (windowTypeIndex == 3) { //繪製系統窗口 DrawSystemWindow(); } else if (windowTypeIndex == 4) { //繪製環境窗口 DrawEnviromentWindow(); } GUILayout.EndVertical(); GUILayout.Space(10); GUILayout.BeginVertical("box"); if (GUILayout.Button("Hide", GUILayout.MinWidth(Screen.width / 10), GUILayout.MinHeight(Screen.height / 20))) { showDebugger = false; } if (GUILayout.Button("Close", GUILayout.MinWidth(Screen.width / 10), GUILayout.MinHeight(Screen.height / 20))) { Destroy(gameObject); _instance = null; } GUILayout.EndVertical(); GUILayout.EndVertical(); } #region Log //Log信息 public class LogInfo { public int uid; public string condition; public string stackTrace; public LogType logType; public DateTime logTime; } List<LogInfo> logCache = new List<LogInfo>();//全部Log LogInfo curLog;//當前選擇的Log Vector2 logScrollPos;//log區域滑動條位置 Vector2 stackScrollPos;//堆棧區域滑動條位置 int logCounter;//log計數器 int infoCounter;//info計數器 int warningCounter;//warning計數器 int errorCounter;//error計數器 bool showInfo = true;//顯示info bool showWarning = true;//顯示warning bool showError = true;//顯示error const float scrollSpeed = 0.02f;//滑動條速度 void LogCallBack(string condition, string stackTrace, LogType logType) { LogInfo logInfo = new LogInfo(); logInfo.uid = ++logCounter; logInfo.condition = condition; logInfo.stackTrace = stackTrace; logInfo.logType = logType; if (logType == LogType.Error || logType == LogType.Exception || logType == LogType.Assert) { errorCounter++; } else if (logType == LogType.Warning) { warningCounter++; } else { infoCounter++; } logInfo.logTime = DateTime.Now; logCache.Add(logInfo); } /// <summary> /// 繪製Log窗口 /// </summary> void DrawLogWindow() { GUILayout.BeginHorizontal(); GUILayout.BeginVertical("box"); //頂部區域 GUILayout.BeginHorizontal("box"); showInfo = GUILayout.Toggle(showInfo, string.Format("info [{0}]", infoCounter)); showWarning = GUILayout.Toggle(showWarning, string.Format("warning [{0}]", warningCounter)); showError = GUILayout.Toggle(showError, string.Format("error [{0}]", errorCounter)); if (GUILayout.Button("Clear", GUILayout.MinWidth(Screen.width / 20), GUILayout.MinHeight(Screen.height / 40))) { curLog = null; infoCounter = 0; warningCounter = 0; errorCounter = 0; logCache.Clear(); } GUILayout.EndHorizontal(); //Log區域 GUILayout.BeginVertical("box"); logScrollPos = GUILayout.BeginScrollView(logScrollPos, GUILayout.MinWidth(Screen.width * 0.8f), GUILayout.MinHeight(Screen.height * 0.3f)); foreach (var log in logCache) { if (!IsShowLog(log.logType)) continue; string infoStr = string.Format("[{0}] {1}", log.logTime.ToString("HH:mm:ss"), log.condition); if (curLog == null) { if (GUILayout.Button(infoStr, GetStyle(log.logType))) { curLog = log; } } else { if (curLog.uid == log.uid) { if (GUILayout.Button(infoStr, logStyle_selected)) { } } else { if (GUILayout.Button(infoStr, GetStyle(log.logType))) { curLog = log; } } } } GUILayout.EndScrollView(); GUILayout.EndVertical(); GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); if (GUILayout.RepeatButton("Up", GUILayout.MinWidth(100), GUILayout.MinHeight(50))) { logScrollPos += Screen.height * scrollSpeed * Vector2.down; } GUILayout.Space(10); GUILayout.BeginHorizontal(); if (GUILayout.RepeatButton("Left", GUILayout.MinWidth(50), GUILayout.MinHeight(100))) { logScrollPos += Screen.width * scrollSpeed * Vector2.left; } if (GUILayout.RepeatButton("Right", GUILayout.MinWidth(50), GUILayout.MinHeight(100))) { logScrollPos += Screen.width * scrollSpeed * Vector2.right; } GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.RepeatButton("Down", GUILayout.MinWidth(100), GUILayout.MinHeight(50))) { logScrollPos += Screen.height * scrollSpeed * Vector2.up; } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); //堆棧區域 if (curLog == null) return; GUILayout.BeginHorizontal(); GUILayout.BeginVertical("box"); stackScrollPos = GUILayout.BeginScrollView(stackScrollPos, GUILayout.MinWidth(Screen.width * 0.8f), GUILayout.MinHeight(Screen.height * 0.3f)); string logStr = string.Format("[{0}] {1}", curLog.logTime.ToString("HH:mm:ss"), curLog.condition); string stackStr = curLog.stackTrace; GUILayout.Label(logStr); GUILayout.Space(10); GUILayout.Label(stackStr); GUILayout.EndScrollView(); GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); if (GUILayout.RepeatButton("Up", GUILayout.MinWidth(100), GUILayout.MinHeight(50))) { stackScrollPos += Screen.height * scrollSpeed * Vector2.down; } GUILayout.Space(10); GUILayout.BeginHorizontal(); if (GUILayout.RepeatButton("Left", GUILayout.MinWidth(50), GUILayout.MinHeight(100))) { stackScrollPos += Screen.width * scrollSpeed * Vector2.left; } if (GUILayout.RepeatButton("Right", GUILayout.MinWidth(50), GUILayout.MinHeight(100))) { stackScrollPos += Screen.width * scrollSpeed * Vector2.right; } GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.RepeatButton("Down", GUILayout.MinWidth(100), GUILayout.MinHeight(50))) { stackScrollPos += Screen.height * scrollSpeed * Vector2.up; } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } /// <summary> /// 獲得樣式 /// </summary> GUIStyle GetStyle(LogType logType) { switch (logType) { case LogType.Error: case LogType.Exception: case LogType.Assert: return logStyle_error; case LogType.Warning: return logStyle_warning; case LogType.Log: return logStyle_info; default: return logStyle_info; } } /// <summary> /// 是否顯示此類型的Log /// </summary> bool IsShowLog(LogType logType) { switch (logType) { case LogType.Error: case LogType.Exception: case LogType.Assert: return showError; case LogType.Warning: return showWarning; case LogType.Log: return showInfo; default: return showInfo; } } #endregion #region Memory /// <summary> /// 繪製內存窗口 /// </summary> void DrawMemoryWindow() { GUILayout.BeginVertical("Box"); GUILayout.Label("總內存:" + Profiler.GetTotalReservedMemoryLong() / 1000000 + "MB"); GUILayout.Label("已佔用內存:" + Profiler.GetTotalAllocatedMemoryLong() / 1000000 + "MB"); GUILayout.Label("空閒中內存:" + Profiler.GetTotalUnusedReservedMemoryLong() / 1000000 + "MB"); GUILayout.Label("總Mono堆內存:" + Profiler.GetMonoHeapSizeLong() / 1000000 + "MB"); GUILayout.Label("已佔用Mono堆內存:" + Profiler.GetMonoUsedSizeLong() / 1000000 + "MB"); GUILayout.EndVertical(); } #endregion #region Screen float FPS;//幀率 float updateFpsInterval = 1;//更新幀率的間隔 float fpsCounter;//fps計數器 float lastUpdateFpsTime;//上一次更新幀率的時間 private void Update() { fpsCounter++; if (Time.realtimeSinceStartup - lastUpdateFpsTime >= updateFpsInterval) { FPS = fpsCounter / updateFpsInterval; lastUpdateFpsTime = Time.realtimeSinceStartup; fpsCounter = 0; } } /// <summary> /// 繪製屏幕窗口 /// </summary> void DrawScreenWindow() { GUILayout.BeginVertical("Box"); GUILayout.Label(string.Format("<color={0}>FPS:{1:F1}</color>", FPS < 30 ? "#FF0000" : "#00FF00", FPS)); GUILayout.Label("DPI:" + Screen.dpi); GUILayout.Label("分辨率:" + Screen.currentResolution.ToString()); GUILayout.EndVertical(); } #endregion #region System /// <summary> /// 繪製系統窗口 /// </summary> void DrawSystemWindow() { GUILayout.BeginVertical("Box"); GUILayout.Label("操做系統:" + SystemInfo.operatingSystem); GUILayout.Label("系統內存:" + SystemInfo.systemMemorySize + "MB"); GUILayout.Label("處理器:" + SystemInfo.processorType); GUILayout.Label("處理器數量:" + SystemInfo.processorCount); GUILayout.Label("顯卡:" + SystemInfo.graphicsDeviceName); GUILayout.Label("顯卡類型:" + SystemInfo.graphicsDeviceType); GUILayout.Label("顯存:" + SystemInfo.graphicsMemorySize + "MB"); GUILayout.Label("顯卡標識:" + SystemInfo.graphicsDeviceID); GUILayout.Label("顯卡供應商:" + SystemInfo.graphicsDeviceVendor); GUILayout.Label("顯卡供應商標識碼:" + SystemInfo.graphicsDeviceVendorID); GUILayout.Label("設備模式:" + SystemInfo.deviceModel); GUILayout.Label("設備名稱:" + SystemInfo.deviceName); GUILayout.Label("設備類型:" + SystemInfo.deviceType); GUILayout.Label("設備標識:" + SystemInfo.deviceUniqueIdentifier); GUILayout.EndVertical(); } #endregion #region Environment /// <summary> /// 繪製環境窗口 /// </summary> void DrawEnviromentWindow() { GUILayout.BeginVertical("box"); GUILayout.Label("項目名稱:" + Application.productName); GUILayout.Label("項目包名:" + Application.identifier); GUILayout.Label("項目版本:" + Application.version); GUILayout.Label("Unity版本:" + Application.unityVersion); GUILayout.Label("公司名稱:" + Application.companyName); GUILayout.EndVertical(); } #endregion }