Unity Singleton GameObject

I’ve seen a few singleton patterns flying around for Unity GameObjects, and thought I’d contribute my own. It will destroy duplicates of the MonoBehaviour, so you can create instances in code and┬áhave a GameObject in every scene with your singleton script attached and it won’t matter.

using UnityEngine;
 
namespace UnityHelper
{
    public abstract class SingletonMonoBehaviour<T> : MonoBehaviour
        where T : SingletonMonoBehaviour<T>
    {
        private static GameObject msSingleton = null;
 
		//
		public static string SingletonName
		{
			get
			{
				return typeof(T).ToString() + "?Singleton";
			}
		}
 
        //
        public static T Instance
        {
            get
            {
				T retVal = null;
 
				// If the singleton pointer is null
				if (msSingleton == null)
				{
					// See if the GameObject already exists
					msSingleton = GameObject.Find(SingletonName);
 
					// If it doesn't then create it
					if (msSingleton == null)
					{
						msSingleton = new GameObject();
					}
				}
 
				// With the GameObject, get our singleton monobehaviour
				retVal = msSingleton.GetComponent<T>();
 
				// If it doesn't exist yet, create it
				if (retVal == null)
				{
					retVal = msSingleton.AddComponent<T>();
				}
 
				return retVal;
            }
        }
 
        //
        private void Awake()
        {
			// If the singleton pointer isn't set yet, set it from this object
			if(msSingleton == null)
			{
				msSingleton = this.gameObject;
			}
 
			// If this monobehaviour is assigned to another GameObject, remove that GameObject
			if(msSingleton != this.gameObject)
			{	
				DestroyObject(this.gameObject);
			}
 
			// Otherwise, initialise this monobehaviour, this is our singleton instance
			else
			{
				msSingleton.name = SingletonName;
				msSingleton.hideFlags = HideFlags.DontUnloadUnusedAsset;
				DontDestroyOnLoad(msSingleton);
 
				OnSingletonCreated();
 
				if (Debug.isDebugBuild)
				{
					Debug.Log("Singleton Created : " + SingletonName);
				}
			}
        }
 
        //
        private void OnDestroy()
        {
			// If this is our singleton instance, then we do want to terminate our singleton
			if(msSingleton == this.gameObject)
			{
				msSingleton = null;
 
				OnSingletonDestroyed();
 
				if (Debug.isDebugBuild)
				{
					Debug.Log("Singleton Destroyed : " + SingletonName);
				}
			}
 
			// Otherwise it is just a duplicate instance
			else
			{
				if (Debug.isDebugBuild)
				{
					Debug.Log("Duplicate Singleton Destroyed " + SingletonName);
				}
			}
        }
 
		// These should be used instead of OnAwake() and OnDestroy() to prevent
		// duplicate instances setting up
		protected abstract void OnSingletonCreated();
		protected abstract void OnSingletonDestroyed();
    }
}

Since OnAwake() and OnDestroy() will get called as well for the duplicates, I’ve added two new methods OnSingletonCreated() and OnSingletonDestroyed() that should be used instead.

Now to implement, just make the monobehaviour you wish to be a singleton inherit off the generic.

namespace MySingletonProject
{
    public sealed class DispatcherMonoBehaviour : UnityHelper.SingletonMonoBehaviour<DispatcherMonoBehaviour>
    {
		//
		protected override void OnSingletonCreated()
		{
			// What you would normally do onAwake
		}
 
		//
		protected override void OnSingletonDestroyed()
		{
			// What you would normally do onDestroy
		}
 
        //
        void Update()
        {
		// do something
        }
    }
}

This code will allow you to destroy the GameObject through normal means as well if you want to be rid of the singleton until it is needed again.

Athena: Word Wrap

Athena: Word WrapOne thing I hate doing is writing classes that will output text, as well as handle special character sequences that get replaced by images. And while all this is happening, having it word wrap as well.

So I wrote a quick word wrap template class today that will do this. It doesn’t give line spacing yet, which I’m still unsure whether or not it should be this.

The way it works is when you create the word wrap object, you can pass to it’s constructor a value for the maximum width a line can be, this can be a floating point value, or an integer (it defaults to integer).

Then you call Parse() and give it a string, it will go through that string, checking the width of characters until the accumulated character widths are greater than the maximum width, or a new line is found. It will output this line of characters and move onto the next bit.

If it finds a word that is longer than maximum width, it will do one of two things. First if it is at the start of a newline, it will cut the word at the point it goes over. If it is already part way into a line, it will cause a new line and put the word on the next line.

I’ve included with this blog entry the header for the word wrap class, it comes as part of a test project in Xcode (it uses the Lorem Ipsum text), but the source and headers should work in another C++ IDE.

Athena Word Wrap Source (Version 1.0.0) (358 downloads)

Athena: Bezier Curves

Bezier CurveWhen animations are exported from Maya through COLLADA files, they come out in a variety of formats depending on how the animation was implemented, and what is being animated.

One format is the bezier curve, a curve made from four points. Two fo the points are the start and end position, and the other two are control points that describe how it should curve.

Bezier Curve ApplicationSince all three axis can be animated, I made it possible to make a 3-component vector bezier class using the bezier class I created, and just calculate the point coefficients once, passing them to the bezier class to get the position. This of course only works if the time length for curves are the same on all three axis.

I’ve made a sample, it is an Xcode project that uses GLUT to render a 2D bezier and a 3D bezier. The code should work with other IDEs. One thing I should warn is that this bezier class only works when the time step is constant between the control point and it’s respective point.

P0 (0, 0) … keypoint 0
P1 (2, 10) … keypoint 1
C0 (0.666667, 42.6212) … control point 0
C1 (1.33333, 10) … control point 1

T0 = (C0 – P0) -> (2, 42.6212)
T1 = (P1 – C1) -> (2, 0)

The above sample is from the COLLADA forum, as you can see the time step is 2 for both T0 and T1. The same post describes how to calculate the S0 if your time step is not constant.

Athena Bezier Source (Version 1.0.0) (401 downloads)

Escape From ASDA (Source)

The quests can now be authored more in Lua. There are conditionals for whether the quest is active, and whether the quest is complete.

I’m tempted to make the entire game in Lua, and just use the application as an intermediate for calling functions and rendering. Then I could just execute functions within rooms / npcs for the relevant dictionary word.

There are still some flaws in the text output, like it doesn’t split up words onto new lines if they are longer than the line width.

Next on the list is 8×8 Board Games, get rid of that horrible green.

Escape From ASDA v2.0.0 (MacOSX) (403 downloads)

 

Escape From ASDA v2.0.0 (Win32) (396 downloads)

Escape From ASDA (Update)

Escape From ASDA - Title ScreenThis weekend I’ve been going through files I’ve been meaning to upload to my website for some time now.

I’ve got all the World of Warcraft addons finished, so I began on the C++ games I made at university.

Escape from ASDA is one of them, I was gonna upload it as it was but after noticing a few memory leaks.

As I started to clean up the code, and then got a little carried away and practically rewrote most of it.

Escape From ASDA - IngameOriginally it used a custom text file format for data, that was % deliminated, now it uses Lua which makes it at lot easier to understand when editting.

I also modified the title screen to use a bit of ASCII art, and made the commands more flexible.

Unfortunately unlike v1.0.0, it does not support mouse input for navigation. And since you can’t seem to change the console caret in MacOSX, I’ve had to make a custom console buffer that I use to render to before outputting.

There are a few more changes I plan to do to make the game script more flexible before I upload the source, but for now where is the binaries for Win32 and MacOSX.

Making it compile on WIN32 again was a pain, much more than it should have been, maybe its just the Microsoft implementation of STL…

Escape From ASDA v2.1.0 (Win32) (406 downloads)

 

Escape From ASDA v2.1.0 (MacOSX) (413 downloads)