• Register
Post tutorial Report RSS Unity Debug Wrapper

A Unity debug option for being able to setup custom toggle-able categories of log types while maintaining the double-click feature in the console window, bringing you right to the relevant line of code.

Posted by on - Intermediate QA/Testing

---------

EDIT: after nearly 3 years I have learned a lot in programming and must say I do not not recommend this approach. For one, the nasty dependency all your code will develop to the DebugUtility.cs class... I had a lot of fun removing references to this when I decided to change my logging. Anyway, feel free to take a look, but - again - I would not recommend using this setup.

---------

This past week I’ve worked on starting the scene saving system (for storing loot outside your own inventory). Currently, items stashed in the Homestead scene’s goody chest will be saved. Unfortunately, a few scrappy bugs have resulted, primarily due to execution order. Fortunately, this has led to the development of a handy debug logging system!

For other Unity users out there, or anyone else interested, I’ve created a wrapper for Unity’s debug logging. This is probably not the best approach, but it has worked well for me so far. This allows the toggling of various log types I’ve setup (ex. just events, Unity messages, etc.), and without losing the focus in the console window (double-clicking the logs & going straight to the line of code). I’ve currently setup different log types for events, messages, networking, & instancing special objects that can all be toggled on/off individually.

Here’s the code (it has been adapted a bit and is untested):

using UnityEngine;
using System.Collections;

public class DebugUtility
{
	public static bool IsActive { get { return (Application.isEditor || Debug.isDebugBuild) && shouldUseDebug; } }
	private static bool shouldUseDebug = true;

	private static bool shouldLogGeneric = true;
	private static bool shouldLogEvents = true;
	private static bool shouldLogMessages = true;
	private static bool shouldLogInstancing = true;
	private static bool shouldLogNetworking = true;

	public delegate void DebugContextLogger(object message, Object context);
	public delegate void DebugLogger(object message);
	
	public static DebugLogger LogNothing; 
	public static DebugContextLogger LogNothingContext; 

	public static DebugLogger LogDelegate; 
	public static DebugLogger LogWarningDelegate; 
	public static DebugLogger LogErrorDelegate; 
	public static DebugContextLogger LogContextDelegate; 
	public static DebugContextLogger LogWarningContextDelegate; 
	public static DebugContextLogger LogErrorContextDelegate;

	// custom log types that can each be toggled on/off individually
	public static DebugLogger LogEventDelegate; 
	public static DebugLogger LogMessageDelegate; 
	public static DebugLogger LogInstancingDelegate; 
	public static DebugLogger LogNetworkingDelegate;
	
	static DebugUtility() 
	{ 
		LogNothing += Nothing; 
		LogNothingContext += Nothing; 
		LogDelegate += UnityEngine.Debug.Log; 
		LogWarningDelegate += UnityEngine.Debug.LogWarning;
		LogErrorDelegate += UnityEngine.Debug.LogError;
		LogContextDelegate += UnityEngine.Debug.Log; 
		LogWarningContextDelegate += UnityEngine.Debug.LogWarning;
		LogErrorContextDelegate += UnityEngine.Debug.LogError;

		LogEventDelegate += UnityEngine.Debug.Log; 
		LogMessageDelegate += UnityEngine.Debug.Log;
		LogInstancingDelegate += UnityEngine.Debug.Log;
		LogNetworkingDelegate += UnityEngine.Debug.Log;
	} 

	static public void Nothing(object Message) {}
	static public void Nothing(object Message, Object context) {}
	
	static public DebugLogger Log() 
	{ 
		return Log (LogType.Log); 
	}

	static public DebugContextLogger LogContext() 
	{ 
		return LogContext (LogType.Log); 
	} 

	static public DebugLogger Log(LogType InLogType) 
	{ 
		if (!IsActive || !shouldLogGeneric)
			return LogNothing;

		if (InLogType == LogType.Log) 
			return LogDelegate; 
		else if (InLogType == LogType.Warning) 
			return LogWarningDelegate; 
		else if (InLogType == LogType.Error) 
			return LogErrorDelegate; 
		else 
			return LogNothing; 
	}

	static public DebugLogger Log(LogType InLogType, LogSourceType InSourceType) 
	{ 
		if (!IsActive)
			return LogNothing;

		if ((InSourceType == LogSourceType.None && shouldLogGeneric) ||
		    (InSourceType == LogSourceType.Event && shouldLogEvents) ||
		    (InSourceType == LogSourceType.Message && shouldLogMessages) ||
		    (InSourceType == LogSourceType.Instancing && shouldLogInstancing) ||
		    (InSourceType == LogSourceType.Networking && shouldLogNetworking))
		{
			if (InLogType == LogType.Log) 
				return LogDelegate; 
			else if (InLogType == LogType.Warning) 
				return LogWarningDelegate; 
			else if (InLogType == LogType.Error) 
				return LogErrorDelegate; 
			else 
				return LogNothing; 
		}
		else return LogNothing;
	}

	static public DebugLogger Log(LogSourceType InSourceType) 
	{ 
		if (!IsActive)
			return LogNothing;
		
		if (InSourceType == LogSourceType.None) 
			return LogDelegate; 
		else if (InSourceType == LogSourceType.Event && shouldLogEvents) 
			return LogEventDelegate; 
		else if (InSourceType == LogSourceType.Message && shouldLogMessages) 
			return LogMessageDelegate; 
		else if (InSourceType == LogSourceType.Instancing && shouldLogInstancing) 
			return LogInstancingDelegate; 
		else if (InSourceType == LogSourceType.Networking && shouldLogNetworking) 
			return LogNetworkingDelegate; 
		else 
			return LogNothing; 
	}

	static public DebugContextLogger LogContext(LogType InLogType) 
	{ 
		if (!IsActive || !shouldLogGeneric)
			return LogNothingContext;
		
		if (InLogType == LogType.Log) 
			return LogContextDelegate; 
		else if (InLogType == LogType.Warning) 
			return LogWarningContextDelegate; 
		else if (InLogType == LogType.Error) 
			return LogErrorContextDelegate; 
		else 
			return LogNothingContext; 
	}
}

public enum LogSourceType
{
	None, Event, Message, Instancing, Networking
}
One downside is getting used to the change in syntax. Here’s some examples:
DebugUtility.Log()(“My generic log!”);
DebugUtility.Log(LogType.Warning)(“A generic warning log”);
DebugUtility.Log(LogSourceType.Event)(“My event log!”);
DebugUtility.Log(LogType.Error, LogSourceType.Message)(“An error SendMessage log!?”);

I can’t take all the credit for this idea, as I discovered the initial inspiration at this link in a comment by Adrian Lavallee, thank you!
Feedback.unity3d.com

With this system in place, I’m finding it much easier to sift through what’s happening and locating issues. Hopefully, I’ll get the initial scene data loading working correctly this coming week.

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: