這次要跟大家分享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 工具,在開發中會更加方便、快速、簡潔,透過以上程式碼,相信大家一定會根據自己的需求製作出更加方便的工具
參考資料
歡迎轉載,並註明出處 !
 
	 
								 
								 
								 
								
 k79k06k02k@gmail.com
  k79k06k02k@gmail.com
您好,我是接觸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