這次要跟大家分享Singleton、Debug Filter工具,Singleton是資料共享工具,能快速的存取、管理跨Script的資料,Debug Filter是 Debug 訊息過濾器,在遊戲上線後一定會想關閉所有的Debug 訊息,以提升遊戲品質與效能
本系列其他文章
- 屬於工程師的專用工具箱(一):便捷工具類別(Utility.cs)
- 屬於工程師的專用工具箱(二):常用工具(Singleton、Debug過濾器)
- 屬於工程師的專用工具箱(三):編輯工具(Editor Tools)
- 屬於工程師的專用工具箱(四):推薦 Plugin [免費篇]
Singleton
在遊戲中一定會有共用資料,而這些資料想要在多個 Scripts 中去做控制、修改,這時我們通常會使用Singleton(單例模式),簡單來說就是使用一個 Static 的類別做控管資料,進而方便的讀取共享資料。
Singleton 工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/********************************************************** // Author : K.(k79k06k02k) // FileName : Singleton.cs // Reference: http://wiki.unity3d.com/index.php/Singleton **********************************************************/ public class Singleton<T> where T : class,new() { private static T _instance; private static object _lock = new object(); public static T Instance { get { lock (_lock) { if (_instance == null) { _instance = new T(); } return _instance; } } } } |
1 2 3 4 5 6 7 8 9 |
using UnityEngine; public class TestClass : Singleton<TestClass> { public void Hello() { Debug.Log("Hello"); } } |
1 |
TestClass.Instance.Hello(); |
Singleton 工具 (繼承 MonoBehaviour 版)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
/********************************************************** // Author : K.(k79k06k02k) // FileName : SingletonObject.cs // Reference: http://wiki.unity3d.com/index.php/Singleton **********************************************************/ using UnityEngine; public class SingletonObject<T> : MonoBehaviour where T : MonoBehaviour { private static T _instance; private static object _lock = new object(); public static T Instance { get { if (applicationIsQuitting) { Debug.LogWarning("[Singleton] Instance '"+ typeof(T) + "' already destroyed on application quit." + " Won't create again - returning null."); return null; } lock (_lock) { if (_instance == null) { _instance = (T) FindObjectOfType(typeof(T)); if ( FindObjectsOfType(typeof(T)).Length > 1 ) { Debug.LogError("[Singleton] Something went really wrong " + " - there should never be more than 1 singleton!" + " Reopenning the scene might fix it."); return _instance; } if (_instance == null) { GameObject singleton = new GameObject(); _instance = singleton.AddComponent<T>(); singleton.name = "(singleton) "+ typeof(T).ToString(); DontDestroyOnLoad(singleton); Debug.Log("[Singleton] An instance of " + typeof(T) + " is needed in the scene, so '" + singleton + "' was created with DontDestroyOnLoad."); } else { Debug.Log("[Singleton] Using instance already created: " + _instance.gameObject.name); } } return _instance; } } } private static bool applicationIsQuitting = false; public void OnDestroy () { applicationIsQuitting = true; } } |
使用時機
如果是純資料(存取Resources、遊戲表格資料),建議使用 Singleton.cs 因為沒有必要繼承MonoBehaviour,省下開銷。
Debug過濾器(Debug Filter)
在開發中會有很多地方使用到 Debug.Log 印出資料,在遊戲上線後要關閉 Debug.Log 就會變得非常麻煩,於是我們就會使用程式碼進行集中控制
1 2 3 4 5 6 7 8 9 |
public class TestClass { public static void Log(object message) { #if Debug Debug.Log(message); #endif } } |
使用方式
- 程式中要 Show Debug Log 的地方都呼叫此方法
- 在 File -> Build Settings -> Player Settings -> Other Settings -> Scripting Define Symbols 新增 Debug 字串
問題
雖然達成了 Debug Log 排除功能,但在我們點選 Unity Console 中的 Debug 訊息兩下,想要知道 Log 是 Script中 哪一行時,就都會指定到集中管理的方法中,這樣造成了Debug上的不方便,還要自己根據 Stack 去查詢是哪一行
改進
這時可以使用自行新增 Debug Class 與 Conditional 的方式,改進上述Debug中的不方便,程式碼是參考以下網站
DebugFilter工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
/********************************************************** // Author : K.(k79k06k02k) // FileName : DebugFilter.cs // Reference: http://liangyenchen.blogspot.tw/2015/09/unity3d-debuglog.html **********************************************************/ #if DEBUG_FILTER using System.Diagnostics; using UnityEngine; public static class Debug { [Conditional("DEBUG_FILTER")] public static void Break() { } [Conditional("DEBUG_FILTER")] public static void ClearDeveloperConsole() { } [Conditional("DEBUG_FILTER")] public static void DebugBreak() { } [Conditional("DEBUG_FILTER")] public static void DrawLine(Vector3 start, Vector3 end) { } [Conditional("DEBUG_FILTER")] public static void DrawLine(Vector3 start, Vector3 end, Color color) { } [Conditional("DEBUG_FILTER")] public static void DrawLine(Vector3 start, Vector3 end, Color color, float duration) { } [Conditional("DEBUG_FILTER")] public static void DrawLine(Vector3 start, Vector3 end, Color color, float duration, bool depthTest) { } [Conditional("DEBUG_FILTER")] public static void DrawRay(Vector3 start, Vector3 dir) { } [Conditional("DEBUG_FILTER")] public static void DrawRay(Vector3 start, Vector3 dir, Color color) { } [Conditional("DEBUG_FILTER")] public static void DrawRay(Vector3 start, Vector3 dir, Color color, float duration) { } [Conditional("DEBUG_FILTER")] public static void DrawRay(Vector3 start, Vector3 dir, Color color, float duration, bool depthTest) { } [Conditional("DEBUG_FILTER")] public static void Log(object message) { } [Conditional("DEBUG_FILTER")] public static void Log(object message, Object context) { } [Conditional("DEBUG_FILTER")] public static void LogFormat(string format, params object[] args) { } [Conditional("DEBUG_FILTER")] public static void LogFormat(Object context, string format, params object[] args) { } [Conditional("DEBUG_FILTER")] public static void LogWarning(object message) { } [Conditional("DEBUG_FILTER")] public static void LogWarning(object message, Object context) { } [Conditional("DEBUG_FILTER")] public static void LogWarningFormat(string format, params object[] args) { } [Conditional("DEBUG_FILTER")] public static void LogWarningFormat(Object context, string format, params object[] args) { } [Conditional("DEBUG_FILTER")] public static void LogError(object message) { } [Conditional("DEBUG_FILTER")] public static void LogError(object message, Object context) { } [Conditional("DEBUG_FILTER")] public static void LogErrorFormat(string format, params object[] args) { } [Conditional("DEBUG_FILTER")] public static void LogErrorFormat(Object context, string format, params object[] args) { } [Conditional("DEBUG_FILTER")] public static void LogException(System.Exception exception) { } [Conditional("DEBUG_FILTER")] public static void LogException(System.Exception exception, Object context) { } } #endif |
使用方式
在 File -> Build Settings -> Player Settings -> Other Settings -> Scripting Define Symbols 新增 DEBUG_FILTER 字串,這樣 Debug Log 就會排除了
後記
這次分享了 Singleton 與 DebugFilter 工具,在開發中會更加方便、快速、簡潔,透過以上程式碼,相信大家一定會根據自己的需求製作出更加方便的工具
參考資料
歡迎轉載,並註明出處 !
您好,我是接觸Unity的新手,關於Debug filter的使用方式,根據https://docs.unity3d.com/Manual/PlatformDependentCompilation.html
所述,確切位置為:
File->Build Setting -> Player Settings -> Other Setting -> Scripting Define Symbols
感謝回報 已修正
From: File -> Build Settings -> Scripting Define Symbols
To : File -> Build Settings -> Player Settings -> Other Settings -> Scripting Define Symbols