Unity tip for the day #2: simple notification server

If you are used to writing code in cocoa like I am, then you have probably become quite addicted to much of the handy API features of cocoa, things like the NSNotificationCenter. .NET and c# might have something like this, but searches for ‘notifications’ turn up a whole bunch unrelated stuff, so I wrote my own:

BBNotificationServer.cs.zip

Just attach this script to a Game Object ( I usually have at least one empty object that is just my holder for all the scene manager scripts.) and you can utilize the notification services.

Here is a quick rundown of how it works:

First off, we have a BBNotificationList class at the top of the file.

public class BBNotificationList {

	private ArrayList objectList =  new ArrayList();

	public string notificationMessage = "";

	public void addObserver(GameObject obj)
	{
		if (!objectList.Contains(obj)) objectList.Add(obj);
	}

	public void removeObserver(GameObject obj)
	{
		if (!objectList.Contains(obj)) objectList.Remove(obj);
	}
	
	public void sendNotice()
	{
		if (notificationMessage == "") return;
		foreach ( GameObject obj in objectList ) {
			obj.SendMessage(notificationMessage,SendMessageOptions.DontRequireReceiver);	
		}	
	}
}

Just a very simple container object that holds a list of GameObjects and a ‘message’. When the sendNotice() method is called, then each object in the list gets sent the message. Simple.

Next we have the ‘server’ which is roughly analogous to the NSNotificationCenter.


public class BBNotificationServer : MonoBehaviour {

	private static BBNotificationServer sharedInstance = null;
	private ArrayList notifications = new ArrayList();
	
	// This defines a static instance property that attempts to find the manager object in the scene and
    // returns it to the caller.
    public static BBNotificationServer instance {
        get {
            if (sharedInstance == null) {
                // This is where the magic happens.
                //  FindObjectOfType(...) returns the first AManager object in the scene.
                sharedInstance = FindObjectOfType(typeof (BBNotificationServer)) as BBNotificationServer;
                if (sharedInstance == null)
                    Debug.Log ("Could not locate a BBNotificationServer object. You have to have exactly one BBNotificationServer in the scene.");
            }
            return sharedInstance;
        }
    }

We are using a singleton pattern here, so you will need to have the script attached to something in your scene. Once you have that then you can get a ref to the server from any other script in the scene like so:

BBNotificationServer  theServer = BBNotificationServer.instance;

or just make calls on it directly like so:

BBNotificationServer.instance.postNotification("DoSomethingNotification");

OK, so the first thing we need to do is be able to add and remove ‘observers’. If you are unfamiliar with the notification center from the cocoa API, then an ‘observer’ is simply an object that wants to be notified by a specific notification.


	public void addObserver(GameObject obj, string notificationMessage) 
	{
		BBNotificationList theList = this.listForNotification(notificationMessage);
		theList.addObserver(obj);
	}
	
	public void removeObserver(GameObject obj, string notificationMessage) 
	{
		BBNotificationList theList = this.listForNotification(notificationMessage);
		theList.removeObserver(obj);			
	}

Again, fairly simple, we have a private method that returns the list for a specific message (and makes a new one if there is not already one) and then we just call the add/remove methods on that list.

Here is that private method:

	private BBNotificationList listForNotification(string message) {
		foreach (BBNotificationList list in notifications) {
			if (list.notificationMessage == message) return list;
		}	
		// we got here so there was no list, so make a new one
		BBNotificationList newList = new BBNotificationList();
		newList.notificationMessage = message;
		notifications.Add(newList);
		return newList;
	}

Right now I just implemented it as an arraylist and we just do a linear search through it. Not super duper fast, but if you only have a handful of notification messages, then it will be plenty fast. If you feel the need for more speed, then just replace this method with something that uses a hashtable and you are all set.

finally, we need to be able to post messages. We already had a look at the actual message posting code in the NotificationList object, and the post notification in the server object is pretty damn simple:

	public void postNotification(string notificationMessage) 
	{
		BBNotificationList theList = this.listForNotification(notificationMessage);
		theList.sendNotice();		
	}

yep, that is it.

So how do we use this? If we have a gameobject that we want to react in some way to a notification then we simply have to register as an observer and implement the method that we are observing.

	void Start() { 
		BBNotificationServer.instance.addObserver(gameObject,"FooAllWidgets");
	}
	
	public void FooAllWidgets()
	{
		this.widget.foo();
	}

And that is it. Very simple!

Note: right after I finished this, I decided to check the one place I forgot to check in my earlier searches, and lo and behold, the Unity community has in fact beaten me to the punch (as usual :-) You can find a javascript implementation of a nice notification center at the Unify Community Wiki. It is a bit different than my implementation, it offers a bit more functionailty, and some extra data handling. Stuff that could be added to this one fairly easily if you needed a c# version.

Cheers!
-B

This entry was posted in Blog, code, Unity. Bookmark the permalink.

Leave a Reply