Learn - smart utilities

A

Coroutiner

During the development process, you might need to use a Coroutine in a class that is not derived from MonoBehavior. The Coroutiner class will help you with that.
1

Setting up the class

First, you need to setup your class with an IEnumerator method.
public class MyClass
{
	IEnumerator MyRoutine(float waitSeconds)
	{
		yield return new WaitForSeconds(waitSeconds);
	}
}
2

Using the Coroutiner

Call Coroutiner.StartRoutine to start the couroutine. An Coroutiner game object will be created in your scene the first time you use this function. See complete code example below.
using UnityEngine;
using System.Collections;
using Twoorb.Utilities;

public class MyClass
{
	IEnumerator MyRoutine(float waitSeconds)
	{
		yield return new WaitForSeconds(waitSeconds);
	}

	void DoAction()
	{
		Coroutiner.StartRoutine(MyRoutine(5));
	}
}
B

Data Filler

The DataFiller class can be very useful when working with JSON strings. It can convert entire classes into a Dictionary, that easily can be used with a good JSON parser like MiniJSON. It can also fill class objects with data from such a Dictionary. Only public variables will be filled.

At Twoorb Studios we use it for specific gameplay/physics settings that is stored in a databased and fetched as json using the WWW class.

One thing to note before using this class is that it uses the System.Reflection namespace, which can be performance heavy. We suggest that you use these methods with low frequency in your project.
1

Creating the class

To use the DataFiller, create a class to use for conversion and filling. For the purpose of this tutorial, we will create a simple class with a few basic variable types called MySimpleDataClass.
public class MySimpleDataClass
{
	public int			  myInt				= 0;
	public string		  myString			= string.Empty;
	public List<string>	myListOfStrings	  = new List<string>();
}
2

Preparing the class for conversion

To convert MySimpleDataClass into a JSON string, create an instance of the class and fill the member variables with some values.
public class MyBehaviour : MonoBehaviour
{
	void Start()
	{
		MySimpleDataClass srcDataClass = new MySimpleDataClass();
		srcDataClass.myInt = 1337;
		srcDataClass.myString = "String Value!";
		srcDataClass.myListOfStrings.Add("A String");
		srcDataClass.myListOfStrings.Add("Another String!");
	}
}
3

Converting the class into a JSON string

Call DataFiller.ToDictionary() to create a dictionary based on the class data.

Secondly pass the dictionary into the MiniJSON.Serialize() method to get the JSON string.
Dictionary<string, object> myDictionary = null;
if(DataFiller.ToDictionary(srcDataClass, out myDictionary))
{
	string json = "";
	json = Json.Serialize(myDictionary);
}
4

Converting the JSON string back to the class object

Converting a json string to a class can be done by first calling the MiniJSON.Deserialize() method to get a Dictionary, create an instance of the class you want to fill (in our case the MySimpleDataClass class) and then use DataFiller.Fill() to move the dictionary data into the class.
MySimpleDataClass destDataClass = new MySimpleDataClass();
myDictionary = Json.Deserialize(json) as Dictionary<string, object>;
if(myDictionary != null)
	DataFiller.Fill(destDataClass, myDictionary);
5

Complete example

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Twoorb.Utilities;
using Twoorb.Utilities.MiniJSON;

public class MySimpleDataClass
{
	public int			  myInt				= 0;
	public string		  myString			= string.Empty;
	public List<string>	myListOfStrings	  = new List<string>();
}

public class MyBehaviour : MonoBehaviour
{
	void Start()
	{
		MySimpleDataClass srcDataClass = new MySimpleDataClass();
		srcDataClass.myInt = 1337;
		srcDataClass.myString = "String Value!";
		srcDataClass.myListOfStrings.Add("A String");
		srcDataClass.myListOfStrings.Add("Another String!");

		Dictionary<string, object> myDictionary = null;
		if(DataFiller.ToDictionary(srcDataClass, out myDictionary))
		{
			string json = "";
			json = Json.Serialize(myDictionary);

			MySimpleDataClass destDataClass = new MySimpleDataClass();
			myDictionary = Json.Deserialize(json) as Dictionary<string, object>;
			if(myDictionary != null)
				DataFiller.Fill(destDataClass, myDictionary);
		}		
	}
}
C

Debug Painter

Using Unity's Debug.DrawLine() method can be a very useful tool when developing a game, but sometimes you want to draw debug geometry during runtime. By default each call draws a debug object for 1 frame, use the duration value to draw the debug object over time.

Do not call the draw functions each frame when using the duration value.
1

Drawing a line

Call DebugPainter.DrawLine() and send in the start point, end point and color to draw a line.
	DebugPainter.DrawLine(start, end, Color.red);
2

Drawing a circle

Call DebugPainter.DrawCircle() and send in the center point, radius and color.
	DebugPainter.DrawCircle(center, radius, Color.blue);
3

Drawing an octagon

Drawing an octagon works the same way as drawing a circle. Call DebugPainter.DrawOctagon() and send in the center point, radius and color.
	DebugPainter.DrawOctagon(center, radius, Color.yellow);
4

Drawing a rectangle

Call DebugPainter.DrawRect() and send in the Rect() object and a color.
DebugPainter.DrawRect(rect, Color.green);
5

Drawing a box

You can draw a box in two ways. You can call DebugPainter.DrawBounds() and send in a bounds object and a color, or you can send in a BoxCollider and a color.
		// Draw using BoxCollider
		DebugPainter.DrawBounds(boxCollider, Color.cyan);

		// Draw using Bounds
		DebugPainter.DrawBounds(bounds, Color.magenta);
6

Drawing a sphere

As with the box, you can draw a sphere in two ways. You can call DebugPainter.DrawSphere() and send in the center point, radius and a color, or you can send in a SphereCollider and a color.
	// Draw using SphereCollider
	DebugPainter.DrawSphere(sphereCollider, Color.green);

	// Draw using Vector3 (center) and float (radius)
	DebugPainter.DrawSphere(center, radius, Color.red);
7

Changing the debug camera

Changing the debug camera By default, the DebugPainter uses the Camera.main for drawing. If you want to use a different camera, just call DebugPainterMono.SetDebugDrawCamera(Camera camera) and send in your desired camera.
// Camera component is attached to the same object as our MonoBehaviour derived class
Camera myCamera = GetComponent<Camera>();
DebugPainterMono.SetDebugDrawCamera(myCamera);

8

Drawing objects for longer than one frame

All of the drawing methods contains an optional parameter called duration. This is by default set to zero, which means that it will draw for one frame only. If you want it to draw for a longer time, you can set the duration to a desired amount of seconds.
	/// 
	/// Should never be called each frame
	/// 
	/// In seconds
	public void DrawDebugInfo(float duration)
	{
		DebugPainter.DrawSphere(sphereCollider, Color.red, duration);
	}

D

Logger

The Logger class enables you use a debug console during runtime. Once the logger is initialized you can enable mail support to report and send logs. You can also setup the logger for crash detection using continuous logging, enabling you to send the crash log to an email. After initialization, you can use the built in Debug.Log/LogWarning/LogError methods in Unity3D as usual.
1

Initializing the logger

Call Logger.Initialize() with no parameters for default behaviour or specify values if you want to enable/disable certain features like Continuous Logging, Save Complete Log and Save all Stack Traces. You should Initialize the logger once at the startup of your application.
using UnityEngine;
using Twoorb.Utilities;

public class LoggerInitializer : MonoBehaviour
{
	public bool							continuousLogging	= false;
	public bool							saveCompleteLog		= true;
	public bool							showGUI				= true;
	public bool							saveAllStackTraces	= false;
	public Logger.EConsoleButtonAnchor	anchorPoint			= Logger.EConsoleButtonAnchor.BottomLeft;

	void Awake()
	{
		Logger.Initialize(anchorPoint, continuousLogging, saveCompleteLog, showGUI, saveAllStackTraces);
		Destroy(gameObject);
	}
}

2

Enabling the email feature

Enabling email in the logger can be a tremendously helpful tool when debugging your application. This gives you and your testers the ability to send a complete log including one or more bug reports to an email of your choice.

Upload the mail.php file (or use your own based on mail.php), download it here, to a web server that supports PHP.

Enable this by calling the Logger.InitializeEmail() method and passing the url to the php file that does the actual mail sending (E.g. http://yourawesomewebsite.com/dev/mail.php), along with the sender and receiver email address.
using UnityEngine;
using Twoorb.Utilities;

public class LoggerInitializer : MonoBehaviour
{
	public bool							continuousLogging	= false;
	public bool							saveCompleteLog		= true;
	public bool							showGUI				= true;
	public bool							saveAllStackTraces	= false;
	public Logger.EConsoleButtonAnchor	anchorPoint			= Logger.EConsoleButtonAnchor.BottomLeft;
	public string						phpMailerURL		= "http://mywebsite.com/mail.php";
	public string						senderMail			= "from@mywebsite.com";
	public string						receiverMail		= "bugs@mywebsite.com";

	void Awake()
	{
		Logger.Initialize(anchorPoint, continuousLogging, saveCompleteLog, showGUI, saveAllStackTraces);
		Logger.InitializeEMail(phpMailerURL, senderMail, receiverMail);

		Destroy(gameObject);
	}
}
3

Enabling Continuous Logging (Crash Detection)

When a crash in your application is apparent, chances are that you won't get the opportunity to first save the log or send it somewhere. Continuous logging enables you to do that at the next startup of your application.
Logger.Initialize(Logger.EConsoleButtonAnchor.BottomLeft, true);
When enabled, the system will continuously store all log messages in a file at Application.persistentDataPath. This file will be removed when application is shutdown properly. If the file is present at startup a window will appear, prompting the user to send the crash log if the mail feature is enabled.
E

Object Pool

Instantiating and destroying game objects frequently can easily cause a performance bottleneck in your game. The ObjectPool class instantiates necessary objects, and recycle objects automatically for you to avoid this problem.

1

Creating the ObjectPool

The object pool works with MonoBehaviour instead of GameObject. When creating an ObjectPool, you send in the source object component, i.e. the component found in a prefab. The pool will use the YourComponent.gameobject for instantiation.

You can also choose how many objects the pool will create when there is no available objects. This is by default set to 10. You might want to set this to a higher number if you know that an large amount of objects of this type will be used frequently.

If you want the non-used objects in the pool to be stored neatly as the child of another gameobject, you can send in a transform parent for this purpose.
public class Gun : MonoBehaviour
{
	public ObjectPool<Bullet>	  bullets 		= null;
	public Bullet				bulletPrefab  = null;

	void Start()
	{
		bullets = new ObjectPool<Bullet>(bulletPrefab, 10);
	}
}
2

Fetching an object

To fetch an object, call the FetchObject() method in your pool instance.
public void Fire()
{
	Bullet bullet = bullets.FetchObject();
	activeBullets.Add(bullet);
	bullet.Shoot(bulletSpawnTransform.position, bulletSpawnTransform.forward, OnBulletDone);
}

3

Clearing the pool

You can call the DestroyObjects() method if you want to destroy all the non-used objects in the pool and clear it.
public void Destroy()
{
	// Destroying the object pool will destroy non-recycled objects as well
	bullets.DestroyObjects();

	// Destroy gun
	Destroy(gameObject);
}
4

Complete example

// Bullet.cs
using System;
using UnityEngine;

public class Bullet : MonoBehaviour
{
	public float	maxLifeTime		= 10;

	float			lifeTime		= 0;
	float			moveSpeed		= 0;
	Transform		cachedTransform	= null;
	Action<Bullet>	onDoneCallback	= null;

	void Start()
	{
		cachedTransform = transform;
	}

	public void Shoot(Vector3 start, Vector3 direction, float speed, Action<Bullet> onDone)
	{
		if (onDone == null)
			throw new UnityException("Can not shoot bullet without a onDone callback!");

		cachedTransform.position	= start;
		cachedTransform.forward		= direction;
		onDoneCallback				= onDone;
		moveSpeed					= speed;
		lifeTime					= 0;
	}

	void Update()
	{
		lifeTime += Time.deltaTime;
		if(lifeTime >= maxLifeTime)
			PerformCleanup();
		else
			cachedTransform.position += cachedTransform.forward * moveSpeed * Time.deltaTime;
	}

	void OnCollisionEnter(Collision collision)
	{
		PerformCleanup();
	}

	void PerformCleanup()
	{
		onDoneCallback(this);
		enabled = false;
	}
}

// Gun.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using Twoorb.Utilities;

public class Gun : MonoBehaviour
{
	public ObjectPool<Bullet>	bullets					= null;
	public Bullet				bulletPrefab			= null;
	public Transform			bulletSpawnTransform	= null;
	public float				bulletSpeed				= 10;

	void Start()
	{
		bullets = new ObjectPool<Bullet>(bulletPrefab, 10);
	}

	public void Fire()
	{
		Bullet bullet = bullets.FetchObject();

		bullet.Shoot(bulletSpawnTransform.position, bulletSpawnTransform.forward, bulletSpeed, OnBulletDone);
	}

	void OnBulletDone(Bullet bullet)
	{
		bullets.RecycleObject(bullet);
	}

	public void Destroy()
	{
		// Destroying the object pool will destroy non-recycled objects as well
		bullets.DestroyObjects();

		// Destroy gun
		Destroy(gameObject);
	}
}


F

State Machine

A finite state machine(FSM) is a well used pattern in game development. The StateMachine class helps you to create and structure your classes into an FSM.
1

Creating the states

To get the state machine up and running you need to create a state enum with states it can use.
public class NPC : MonoBehaviour
{
	public enum EState
	{
		Idle,
		Walking,
		Dead
	}
}

2

Initializing the machine

Now that we have a set of states, we can setup the state machine. When creating the machine, we pass in the type of the state enum we just created.
StateMachine<EState> stateMachine = null;

void Awake()
{
	stateMachine = new StateMachine<EState>();
}
3

Setting up the states

Next, we need to tell the machine what it should do on each state. We do that by using the AddState() method. Specify up to three callbacks for each state; on enter, on update and on leave. Each of these callbacks can be set to null.
void Awake()
{
	cachedTransform = transform;

	stateMachine = new StateMachine<EState>();
	stateMachine.AddState(EState.Idle);
	stateMachine.AddState(EState.Walking, WalkingEnter, WalkingUpdate, WalkingLeave);
	stateMachine.AddState(EState.Dead, DeadEnter);

	// Trigger the initial state
	stateMachine.TriggerState(EState.Idle);
}

void WalkingEnter()
{
	Debug.Log("Started walking!");
}

void WalkingUpdate()
{
	cachedTransform.position += cachedTransform.forward * walkSpeed * Time.deltaTime;
}

void WalkingLeave()
{
	Debug.Log("Stopped walking!");
}

void DeadEnter()
{
	PlayDeathAnimation();
}

4

Updating the machine

The state machine needs to be updated, if your states aren't being called then it is probably because the Update function isn't called.
void Update()
{
	stateMachine.Update();
}
5

Triggering a state

After the setting up the states, all you have to do to use it is to call the TriggerState() method and pass in the desired state.
public void TakeDamage(int damage)
{
	// Check if we are already dead
	if(stateMachine.HasCurrentState && stateMachine.CurrentStateType == EState.Dead)
	{
		Debug.Log("Already dead!");
		return;
	}

	health -= damage;
	if(health <= 0)
		stateMachine.TriggerState(EState.Dead);
}
G

State Machine Class

Tutorial is under construction, check the forums for support.
H

Editor GUI Extension

Making editor tools during the development of your project can be a real time saver. The editor GUI extension helps you to get a cleaner look and the ability to group members into separate menus.
1

Creating a data class

First, we need to create a class which we will create a custom inspector class for later.
using System;
using UnityEngine;

public class MyClass : MonoBehaviour
{
	public int		firstInt		= 0;
	public int		secondInt		= 0;
	public string	firstString		= "";
	public string	secondString	= "";
	public bool		firstBool		= false;
	public bool		secondBool		= true;
}
2

Creating the custom inspector

Next, we'll create the custom inspector class for our data class. Make sure you save this class in a folder named "Editor".
using System;
using UnityEditor;
using Twoorb.Utilities.Editor

[CustomEditor(typeof(MyClass))]
public class MyClassInspector : Editor
{
	public override void OnInspectorGUI()
	{
		MyClass myClass = target as MyClass;
	}
}
3

Creating groups

The main usage of the EditorGUIEx is BeginGroup() and EndGroup().

Remember to call EndGroup within an if-statement checking if BeginGroup returns true (meaning that the group is open). Using the same key for several groups will cause all of them to open and close when one of them is toggled.
using System;
using UnityEngine;
using UnityEditor;
using Twoorb.Utilities.Editor;

[CustomEditor(typeof(MyClass))]
public class MyClassInspector : Editor
{
	public override void OnInspectorGUI()
	{
		MyClass myClass = target as MyClass;
		if(EditorGUIEx.BeginGroup("Integers", true, false, "myclass_ints"))
		{
			myClass.firstInt = EditorGUILayout.IntField("My First Int", myClass.firstInt);
			myClass.secondInt = EditorGUILayout.IntField("My Second Int", myClass.secondInt);

			EditorGUIEx.EndGroup();
		}

		if (EditorGUIEx.BeginGroup("Strings", true, false, "myclass_strings"))
		{
			myClass.firstString = EditorGUILayout.TextField("My First String", myClass.firstString);
			myClass.secondString = EditorGUILayout.TextField("My Second String", myClass.secondString);

			EditorGUIEx.EndGroup();
		}

		if (EditorGUIEx.BeginGroup("Booleans", true, false, "myclass_bools"))
		{
			myClass.firstBool = EditorGUILayout.Toggle("My First Boolean", myClass.firstBool);
			myClass.secondBool = EditorGUILayout.Toggle("My Second Boolean", myClass.secondBool);

			EditorGUIEx.EndGroup();
		}

		if(GUI.changed)
			EditorUtility.SetDirty(target);
	}
}
4

Using DrawInspector and DrawInspectorGroup

If you don't need to manually add GUI elements, then you can use DrawInspector and DrawInspectorGroup and pass in a SerializedObject.
public override void OnInspectorGUI()
{
	if(EditorGUIEx.BeginGroup("MyClass"))
	{
		EditorGUIEx.DrawInspector(serializedObject);
		EditorGUIEx.EndGroup();
	}

	// Will produce same result as above
	EditorGUIEx.DrawInspectorGroup("MyClass", serializedObject);
}

5

The result

Our strings, ints and bools are now grouped nicely. If you want to be able to toggle your entire groups, make sure to set the toggleable-field to true in the EditorGUIEx.BeginGroup() method. The result of collapsing a group can be shown in the picture below in the "Booleans" group".

EditorGUIEx_Result
6

Using CustomDraw

All members will be drawn with the EditorGUILayout.PropertyField unless you specify a custom draw class. There is currently 2 custom draw methods in EditorGUIEx. Slider – Supports Int values with a min/max range and is displayed as a slider Ignore – Ignore displaying a specific property Create your own custom draw classes by inheriting from the EditorGUIEx.CustomDraw and override the DrawProperty method. See example below:
using System;
using UnityEngine;
using UnityEditor;
using Twoorb.Utilities.Editor;

[CustomEditor(typeof(MyClass))]
public class MyClassInspector : Editor
{
	class TextFieldMaxLength : EditorGUIEx.CustomDraw
	{
		int maxLength = 0;

		public TextFieldMaxLength(string propertyName, int max) : base(propertyName)
		{
			maxLength = max;
		}

		public override void DrawProperty(SerializedProperty property)
		{
			if (property.propertyType != SerializedPropertyType.String)
				throw new UnityException("Can not use TextFieldMaxLength for non String value!");

			property.stringValue = EditorGUILayout.TextField(string.Format("{0}(max={1})", property.name, maxLength), property.stringValue);
			if(property.stringValue.Length > maxLength)
				property.stringValue = property.stringValue.Remove(maxLength);
		}
	}

	public override void OnInspectorGUI()
	{
		EditorGUIEx.DrawInspectorGroup("MyClass", serializedObject, true, true, true, false, "", 
										new TextFieldMaxLength("firstString", 5), 
										EditorGUIEx.Ignore("firstBool"), 
										EditorGUIEx.Slider("firstInt", 0, 100)); 
	}
}
myclass
I

Version Incrementer

Increasing the build version manually when targeting mobile platforms like iOS, Android and Blackberry can easily be forgotten. The Version Incrementer offers a solution to do this automatically.
1

User interface

Initially, the version incrementer will appear automatically after each build you do to either iOS, Android or Blackberry, letting you increment versions by using the controls in the window.

version
J

Fetch Object Asset

If you have any objects or assets in your project that originally resides outside your Unity project, using copy/paste is not really a good option.

The fetch object asset lets you specify file paths relative to your project folder and a relative destination folder. It fetches the assets in the remote location and copies them into the desired destination folder.
1

Creating a fetch object list

Right click in the project view of your Unity project where you want you fetch object list and navigate to Create->FetchObjectList. [Picture of choosing the "FetchObjectList" option in the menu]
2

Specifying which objects to fetch

The destination field in the object inspector will set where the files in the file paths list will be fetched to. The destination editor field works the same way with the only difference that this is where the files in the file path editor list will be fetched to.

A valid path for the file paths in the lists is that they should be appendable to Application.dataPath. ex.

Application.dataPath + path in list = valid.

[Picture of the fetch object asset inspector]

When this is specified, all you have to do to get the objects is to press the button "Fetch Objects".
K

Editor Screenshot & Remove Empty Folders

1

Editor Screenshot

The editor screenshot class is made to easily take a screenshot of the game view only. screenshot

Taking a screenshot
Navigate to Window->Utilities and press Screenshot to open the Screenshot tool, enter a file name and choose if a date will be appended and which format to use, finally press Capture to take a screenshot.
2

Remove Empty Folders

If you are collaborating on a project with other developers, chances are that a folder's meta file will still be left in your project after all the content in it is removed. Manually deleting these folders can be boring and tedious work. Our tool helps you with that.

Removing all the empty folders in your project
Navigate to Assets and press Remove All Empty Folders. The system will then search for all the empty folders in your project and try to remove them.
L

Input Window

Use the InputWindow in the editor to provide an easy to use interface for custom value inputs.

inputwindow
1

Parameters

The input window can be shown with a variation of input fields and extending the input window to support additional data types can easily be done.

Define the types using the template function Show, supply a callback function and define default values for the fields. Optionally you can enter labels which is recommended if you develop for other users then yourself, if you do not provide labels then the type name will be displayed.
InputWindow.Show<string, float>("Data Settings", OnDataSettings, "Default Value", 0.5f, "Data String", "Data Float");
2

Handle response

Define a callback function and supply a bool parameter and the same parameters as defined in the Show function. The bool parameter is true if the user pressed the 'OK' button, false if the 'CANCEL' button is pressed or the window is closed.
static void OnDataSettings(bool success, string data1, float data2)
{
     if(!success)
     {
          Debug.Log("User canceled!");
          return;
     }

     Debug.Log(string.Format("User entered: {0} and {1}", data1, data2));
}
3

Extra information

Use the SetHelper function to display an information area.
window.SetHelper("Remember to set the Data String value!", MessageType.Info, false);
4

Complete Example

using UnityEngine;
using UnityEditor;
using Twoorb.Utilities.Editor;

public class DataSettingsEditor : Editor 
{
	[MenuItem("Tools/Data Settings")]
	static void ShowInputWindow()
	{
		// Show the window (Only need to store the window instance if we plan to use the SetHelper function)
		InputWindow window = InputWindow.Show<string, float>("Data Settings", OnDataSettings, "Default Value", 0.5f, "Data String", "Data Float");

		// Add helper info
		window.SetHelper("Remember to set the Data String value!", MessageType.Info, false);
	}

	static void OnDataSettings(bool success, string data1, float data2)
	{
		if(!success)
		{
			Debug.Log("User canceled!");
			return;
		}

		Debug.Log(string.Format("User entered: {0} and {1}", data1, data2));
	}
}