Progress (Week of Oct. 4-10) : Unity Debug Wrapper

Jon: 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!
http://feedback.unity3d.com/suggestions/editor-clickable-stacktrace-on-

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.

Lastly, Andrew is continuing to work on the Water Cave dungeon.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s