New team, new opportunities! As you may remember from my previous posts about my Senior Production project here at Champlain, I’m on a new team now, and work has started for the Spring semester.


As a backend and tools programmer, one of my first tasks was to create a Message System for the game (also known the “Observer” pattern or just simple Events).

Our game Office Mayhem is a fast-paced couch competitive multiplayer game, in which the players do menial office tasks as quickly as possible and earn points, striving to be Employee of the Day.

The Message System was initially proposed as a way to keep track of certain statistics of the players (like times dashed, number of times a computer was used, etc) to award the players “accolades” after each round for extra points. Things like, “Paper Pusher,” awarded for copying the most papers.

We’re still working on the design of the accolades, but the Message System is useful enough for other things that it was assigned to me to create it.
We are currently using it to play sounds, as the audio code was sprinkled and repeated all over the codebase. On top of that, I created a Service Locator for the audio, as well as for the future if we ever need other systems like it.

Put the Message System and the Service Locator together, and we have a robust and extensible system for many things, either refactored out of the current code or new services in the future.


This was the plan: Create a Service Locator, a Message System, and the relevant message and service. As this project is in Unity, these were written in C#.

The Message System (and the Service Locator too, actually) are both global, static classes, the Locator being a static singleton.

The Message System uses a dictionary of lists to keep track of all of the currently registered Listeners

public class MessageSystem
{
    private static Dictionary<MessageType, List<MessageListener>> listeners;

    // ... other code ...

    // Fire!
    public static void Fire(Message message)
    {
        // For each object that has registered as a listener of this type...
        foreach (MessageListener listener in listeners[message.type])
        {
            // ...call it's handleMessage()
            listener.HandleMessage(message);
        }
    }
}

to avoid looping through a potentially very large list of listeners and checking types, and instead only notifying Listeners who actually care about the Message.

Now, of course, this is standard for a Message system like this. What is also standard, and that I really don’t like, is firing a message like this:

MessageSystem.Fire(new PlaySoundMessage("sound_name"));

I just find this so dissatisfying. Why should I nest functions like this? It feels so clumsy. And the only reason I need to do this at all is for the unique argument lists each individual message has for its constructor.

So, for the PlaySoundMessage (and for future messages), I have a public static Fire() method, like so:

public static void Fire(string sfxName, float volume = 1.0f)
{
    MessageSystem.Fire(new PlaySoundMessage(sfxName, volume));
}

As you can see, this will create a new message and fire it (just like before), although now we can simply write

PlaySoundMessage.Fire("sound_name");

which is much cleaner.


The current codebase has been refactored to use this new system, and all is well. On top of that, we have a nice Message system for future use.

We’ll see how much we can get out of this.

Advertisements