Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
July 28, 2014
arrowPress Releases
July 28, 2014
PR Newswire
View All
View All     Submit Event





If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 
A Simple Observer Pattern for Unity 4.2
by Darrel Cusey on 08/29/13 01:51:00 pm   Expert Blogs   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

This post was originally published at Lakehome Games here.

The Unity Package for this article can be downloaded here.

If you have been developing in Unity for awhile, you probably have found yourself writing code like this:

GameObject.Find("BigBoss").GetComponent.AddHealth(-20F);

Although code like this is fully functional, I am going to propose that you shouldn't be doing it.  Here are some reasons why:

  1. If BigBoss loses its BossManager script in exchange for a generic EnemyManager script, all the scripts that try to reference the BossManager will break (even if EnemyManager does have an AddHealth() function).
  2. Whenever a new script is created that must also be notified of any health changes to BigBoss, you must modify every script that performs those changes (so that it also notifies the new script).
  3. If the AddHealth() function is changed to a UpdateStats() function, this will also break all scripts that reference this funtion.

In other words, what this does is create strong coupling between your classes.  When you do this, each class must have intimate knowledge of the class it is trying to access.  As your project grows, this will leads to hours of wasted time, unnecessarily complex code, and an inflexible framework.

One possible solution to this is to implement an Observer Pattern for your project.  Normally, these kinds of systems can be done with Events, Delegates, and Generics.  However, I would guess that most Indie game developers would struggle with the more esoteric formulations of this design pattern.  And while learning new things is great, sometimes you just want to finish your game.  This article will demonstrate an extremely simplified version of the Observer Pattern that will allow your classes to:

  1. publish and subscribe to events easily;
  2. reduce their coupling with other classes;
  3. easily expand the number and types of messages they can publish/subscribe to.

If you haven't done so already, grab the Unity Package for this article, and open up the MessageManager script so you can follow along.  Let's start with a Process Flow diagram that shows what's going on (time moves from top to bottom):

simple_observer_2

At any point in the program, classes can register their interest in certain events with the MessageManager.  At any other time, any other class can generate a new message and send that message (with all the event information about the event) and send that on to the MessageManager.  The MessageManger will then turn around and send that event to all classes that have registered interest in that event.

The MessageManager knows which classes and methods it should send events to by using a little LINQ code as seen in the SendToListeners() method:

public void SendToListeners(Message m){
 foreach (var f in listeners.FindAll(l => l.ListenFor == m.MessageName)){ 
   f.ForwardToObject.BroadcastMessage(f.ForwardToMethod,m,SendMessageOptions.DontRequireReceiver);
   }
 }

There is one caveat to this solution -- namely, all classes that will participate in publishing and subscribing to messages must have a reference to the MessageManager object.  Having just one "hard-coded" reference, though, is much better than having hundreds :)

One way you can easily fulfill this requirement (and the method I chose) is to simply make all classes that will be sending and receiving events a child  of the MessageBehaviour class.  We do this by creating an empty object named "World" and attaching the MessageManger script to it.

public class MessageBehaviour : MonoBehaviour {
protected MessageManager Messenger;
 public void Start(){ 
   Messenger = GameObject.Find("World").GetComponent();
   OnStart();
 }
 protected virtual void OnStart(){
 }
}

...then each of our classes that will participate in publishing and subscribing to messages only needs to inherit from the MessageBehaviour class and implement the OnStart() method:

public class BigBoss : MessageBehaviour {
  protected override void OnStart () {
    // put code here that you would normally put in Start()
  }
}

We'll do something very similar with all Message classes as well -- each one will Inherit from a base Message class.  This still keeps our inheritance hierarchy extremely simple:

simple_observer_1

I like using dedicated classes for messages because then I incorporate "convenience functions" right into the message itself.  I didn't do this for this sample, but you can imagine a subscriber needing the message information in a particular format.  Let's say you have an IP address that is represented internally in the class as a 32-bit UINT.  A subscriber may instead need this information as a string -- if your message is a class, then you can simply make a GetIPAddresssString() method in the class which will guarantee that all subscribers re-format the data in exactly the same way.

As you can see though, we need a way for our MessageManager to be able to handle LOTS of different message classes -- some may only have a name/value pair while others could contain dozens of attributes.

To allow any number of different Message classes to be used with this system, we use inheritance again (composition works fine, though, as well).  We use a base Message class, and all other message inherit from it.  Because we are lazy programmers, and don't like re-writing getters and setters for every child class of message, we'll call the base constructor right in the signature like this.  We can see this in the definition of the NewPlayerMessage:

public class NewPlayerMessage : Message {
 public int PlayerGUID {get; set;}
 public NewPlayerMessage(GameObject s,string n,string v, int p) : base(s,n,v)
 {
   PlayerGUID = p;
 }
}

Now we can send either a generic Message, or the fancier NewPlayerMessage to the MessageManager's SendToListeners() method.

Some things you may want to add to this system would include (again, I left these out to keep things as simple as possible):

  • An unsubscribe function to allow classes to stop receiving messages that no longer interest them
  • An automatic Message GUID system that would allow all message to have a globablly-unique ID that would be required for...
  • An acknowledgement system to allow classes to acknowledge to the sender that they did in-fact receive a given message

I hope you are able to use this implementation of the Observer pattern in your next Unity project.  

As always, thanks for reading.


Related Jobs

Integrated Military
Integrated Military — Remote Work Possible, Florida, United States
[07.27.14]

Software Engineer
Cloud Imperium Games
Cloud Imperium Games — Austin, Texas, United States
[07.25.14]

DevOps Engineer
Cloud Imperium Games
Cloud Imperium Games — Austin, Texas, United States
[07.25.14]

Animation Programmer
Cloud Imperium Games
Cloud Imperium Games — Austin, Texas, United States
[07.25.14]

Server/Backend Programmer






Comments


Rob Graeber
profile image
I'm kinda confused about the benefits of using this pattern for components. It seems very involved if you are subclassing monobehavior and having to write subclasses for messages. Of course events and delegates have their place, but I'm not sure if it's appropriate to do every component method call this way. This basically just seems like a faster version of SendMessage(), the tradeoff being more code to write.

For example, the traditional way:
#1: GameObject.Find("BigBoss").GetComponent(BossManager).AddHealth(-20F);
#2: GameObject.Find("BigBoss").SendMessage("AddHealth", -20F);

Versus (if I understand it correctly):
Subclassing a message to have a float property
Make sure the BossManager component was added as a listener
HealthMessage message = new HealthMessage(GameObject.Find("BigBoss"), "AddHealth", -20F);
MessageManager.SharedManager().SendToListeners(message);

Btw apparently gamasutra's comment system doesn't like angle brackets, I noticed your code is missing the <> references.

Marc Schaerer
profile image
In your example there is no benefit because its none suited for a pattern. You have a 1 : 1 relationship because you want to impact exaclty one specific object with 1 specific message.

The Observer pattern is designed and meant for 1 to many relationships, for example where the big boss would send out an 'attack that player' message and an undefined, flexible amount of ships would respond to it and attack the player.

If used in such a scenario, the benefit in your named example above is performance.

In the traditional way:
The first call can cache the BossManager component and just call AddHealth in all future cases, the way its shown in the article above.

The second way could cache onlöy the big boss object and it will always generate garbage that needs to be cleaned up (not only for the data you send but the string 'AddMessage' too). Additionally Unity messages require MonoBehaviors on the other side and the behaviors and their game objects must be active.

In both cases though you will in consequences have the hardcoded 'AddHealth'

To make this problem worse you could use SendMessageUpwards or BroadcastMessage which both iterate through the scene hierarchy on each call and each impacted object, which can easily bring your game performance to unplayability if you throw in a 4-5 figure amount of game objects into a scene with some more or less deep hierarchies


In the above setup

Using the Observer Pattern, you disconnect the sender and receiver and you remove an explicit dependency on how the function is called on the different actors in this setup.
To what degree you can disconnect them depends on your implementation. With a direct listener - publisher relationship its somewhat disconnected. If you on the other hand have an OSX - iOS style global Notification Manager or use IoC (Inverse of Control) style approaches, its completely disconnected and independent, which makes your code not only highly reusable but unlike your traditional way, this code also becomes testable through Unity Tests and can be written (within limits) using TDD paradigms.

Darrel Cusey
profile image
Thanks for the comment, Rob.

The Observer Pattern helps more as your code base gets more complex. The more classes you have that need to be notified of each others' changes in state, the more it helps.

Let's say you have 10 classes (let's call these S classes) that need to be notified whenever there are changes to attributes in 5 other classes (let's call these P classes). In order to keep everyone properly up to date, using the traditional method you would need to notify each of the 10 S classes from each of the 5 P classes. That's would mean 50 notifications.

Using an Observer pattern, you only need 5 notifications from the 5 P classes, and 10 listener registrations from the S classes for a total of only 15 notifications. The fact that there are still _actually_ 50 notifications happening "under the covers" by the Messenger class is somewhat irrelevant to you the programmer because you only have to maintain the 5 notifications and the 10 registrations -- so to you, that's only 15 elements to manage instead of 50.

With the Observer pattern, the Publishers don't have to know or care what other classes need to be notified, they just "fire and forget."

Additionally, your summary of how to send a message isn't 100% correct:

1) The first gameObject attribute in the Message construction is _not_ the target gameObject that would receive the message -- I think this is probably why this was so confusing for you. That would defeat the whole point of the Observer Pattern after all. The first gameObject (notice the case) is the gameObject that is _sending_ the message. Technically, this isn't even needed -- you could remove that attribute if you want as no part of the implementation relies on know who the sender is. It's just there if you wanted to put in an acknowledgement system. So, in other words, the Find is not needed using the Observer pattern.

2) I'm not sure where the "SharedManager" is coming from in your code above -- that's not needed. The standard call to send a message to all listeners looks like this:

Messenger.SendToListeners(new Message(gameObject, "MessageName", "MessageValue"));

3) This is just stylistic preference, but you don't need to create the message separately from the SendToListeners function call.

So, let's look at your "Versus" section again in this light:

1. Subclassing a message: Having well-defined inter-class communication is a good idea anyways, plus it allows your messages to have their own method to allow for re-formatting attributes in a coherent way - which is explained in the article. You'd probably want to do this anyways.

2. Registering a listener: The class that is going to respond to a state-change would have to have some way to detect that state change and respond to it anyways (or else, why would it be interested in that state change in the first place). We are effectively just replacing a if/then/else block with a RegisterListener function call. No more work here than what you'd have to do without an Observer pattern.

3. Send the message: As previously mentioned, can be done in a single line of code. Also, only has to be done _once_ no matter how many listeners there are. Using the traditional method, you would have to write a notification for _every_ class that needs to be notified. Using an observer pattern, you write just a single notification and the Messenger takes care of the rest.

Hope that clears things up for you, Rob. Happy coding!

Rob Graeber
profile image
Oh cool, so it's like Flash AS3's eventlistener system. Usually in Unity I just use a combination of direct polling and SendMessageUpwards(), but I see how it'd be useful in complex projects.

Might I make a suggestion though, instead of subclassing monobehavior to just pass a MessageManager reference, make MessageManager either a singleton or a static class. Seems like that would make your life a lot easier.

Darrel Cusey
profile image
Rob,

It's a toss-up between sub-classing from MessageBehaviour (which is the path I chose), or putting the GameObject.Find for the MessageManager into the Start() function of every class. I chose the former because I tend to avoid singletons, probably -- but to each his own :)

Rob Graeber
profile image
Well the singleton way is not using GameObject.Find, it's accessing that MessageManager component/instance statically. IE either having MessageManager assign itself to a static _sharedInstance property in Init() or Start() functions then accessing via static functions.

So in the end, you wouldn't need to subclass and your method calls would look like:
1. MessageManager.SharedManager().SendToListeners(message);
2. MessageManager.SendToListeners(message);

But of course I love singletons, and I try not to subclass monobehavior.

Luis Guimaraes
profile image
I'm huge fan of using the hierarchy to the max, and a lot of that is using it to know "where" everything is. The fact it's even called "hierarchy" instead of simply "tree" spares analogies.

Combining the powerful hierarchy with GetComponent, some few Singletons, Delegates, Interfaces, and physics-triggered encounters, all communication problems are solved. After my first messy project, Find() is dead for good.

Marc Schaerer
profile image
Great Article, thank you for sharing your approach Darrel
For those new to programming and patterns this is definitely a solid introduction and an out of the box usable solution. Now they just need to identify the cases where it can be applied to :)

Jaroslav Stehlik
profile image
Nice article. But in my opinion, using messages and calling upon hierarchy and rely on GameObject name is quite bad practice. It's too easy to break code because of reparenting or renaming objects also sendMessage is heavy for GarbageCollector. Also there is a lot of string compares to be made. So in general, I would not recommend to use this approach anywhere. Maybe when you are in stage of prototyping but that code should be replaced when actual development begin. I think better Idea is to use delegates and maybe centralized delegate manager. They are much faster and memory friendly but they have to be registered and unregistered when you don't need them again. It is a little bit more work, but in the end it will pay off. Specially on mobile devices.

Ashkan Saeedi Mazdeh
profile image
SendMessage might make problems on mobile and with garbage collector if your events are frequent but we've used them successfully even in big projects without much performance problems. They remove the problem of registering and unregistering delegates and also it's possible to do some caching and using reflection implement your own sendMessage methods.
For many situations they can work well and become the reason for much simpler code.

You just know that you need a service and know the name of callback, someone will call that on you automatically. It's something like message passing systems in message oriented systems.

It's not great for every solution but it's nice in many.

Igor Hatakeyama
profile image
It's interesting but as i'm no programmer, I don't get exactly what's the point of it. Can you give a practical example of a scenario that you would use it?

Jonathan Jennings
profile image
Darrel lists the example at the top but it is pretty simple basically if you picture a boss fight and you had several enemies drop into the scene using this you could tell all 10 enemies to attack the player in one call without having to define each enemy specifically.

I like to think of it as a megaphone calling out orders and certain parts of the game only respond to specific orders when given. It also can be helpful for optimization purposes as well judging by the other comments I just know I've always seen the pattern used to more tightly regiment specific game mechanics.

Another use I've seen for it is with those screen clearing kickass weapons, if you want to easily kill all enemies on screen you could call a universal die function and clear the screen. Again just really useful when trying to communicate to multiple items in your scene quickly!

Hope this helps!

Igor Hatakeyama
profile image
Wow man! Now I see! I helped a lot, thank you Jonathan :)

Curtiss Murphy
profile image
Say you have a class for Player. And say the player changes in some way (takes damage, gains a level, new clothing, etc...). A bad way to handle this is to have the player class make explicit calls to every thing in your game that cares, including the User Interface, every enemy, your resource manager, level timers, etc...

GameObject.Find("UI_Controller").GetComponent().HandlePlayerChange d(this);
GameObject.Find("Enemy_Manager").GetComponent().HandlePlayerChange d(this);
GameObject.Find("Level_Timer").GetComponent().HandlePlayerChanged( this);

and so on. Now, also imagine you had lots more events, like "Player Died", "Player Reached End of Level", "Player Jumped", etc... and you had LOTS more things that need to know about this behavior. Now you have a many-to-many nightmare of hard-coded logic.

Brian Noon
profile image
This sounds similar to the Notification Center from the unity wiki:
http://wiki.unity3d.com/index.php?title=NotificationCenterGeneric
s

Which works well.

Finding objects by name is regarded as a slow operation (on mobile especially), and even GetComponent is something to be careful of overusing. Better to find by tag, or layer if possible. Of course, whether it's an issue depends on whether you're doing it on multiple objects every frame, or just caching it once and calling it a day...

Arturo Nereu
profile image
Thanks for sharing this, is very interesting. I just have a question, the LINQ part is a big performance issue on this implementation? I´ve read that avoiding the use of LINQ specially on mobile is a good practice.

Great diagrams and implementation btw.

Darrel Cusey
profile image
Arturo,

Yep - you are correct. It especially causes havoc with the garbage collection in Unity. In my own experiences with using this solution, though, it's not terrible. It would probably make a difference if you were developing for the iPhone and were trying to do an RTS. Still, I love LINQ (probably just because of my DBA background), so I'm hoping that it will get more efficient over time. I guess you could say I'm "betting" on the technology by spending time learning its ins and outs.

John Maurer
profile image
You should really try to wrap your steps into a common call, makes usage eaiser

Darrel Cusey
profile image
Thank you everyone for the feedback. I'm a self-taught programmer, so all your comments, encouragement, and suggestions are greatly appreciated :D

Simon Dean
profile image
While acceptable for beginners, it's unlikely advanced Unity developers would use such a pattern for the following reasons:

a) SendMessage is slow ( uses Reflection ). Delegates/Events(Action) are faster.

b) foreach usually causes unnecessary allocation thereby feeding the gc.

c) LINQ is ok if you are using the stack, but will feed the gc if using the heap, so requires caution and experience.

Darrel Cusey
profile image
@Simon,

You should write an article demonstrating a fast and efficient Observer patters with events and delegates -- perhaps a Gamasutra article :D My goal for this article was to write a very simple implementation, so I think many readers would enjoy seeing a more efficient one.

Jason Kenney
profile image
Hmm, I'm not familiar with the Unity platform, but in the web langage world, there is a huge benefit to message passing, though usually its a string that can be parsed (JSON for example).

The reason for that is, you just need the parsing class to understand the message and either use or discard it. As for reasons why it could be useful for games:

1. Concurrency: passing data in a immutable state means you don't get headaches dealing with shared memory.

2. Law of Demeter, generally you want loose coupling, sending messages means, you only need to send a message, and respond to messages that class cares about.

3. Message sending is getting into SmallTalk, and SmallTalk was damn cool :)

Simon Dean
profile image
@Darrel The pattern above achieves it's goal of loose coupling. However you can have less allocation ( thereby not feeding the gc ) and it could be faster by not using Reflection-based SendMessage ( but we're perhaps talking fractions of a millisecond! ). The LINQ can be removed entirely.

Rather than add a MessageManager, I've made Messages broadcast themselves when using the ctor with parameters using a static event. I've also introduced a message type enum ( to avoid the allocation that the string-based message.name has ) and subscribe/unsubscribe.

I personally wouldn't use events quite like this with a centralized events system and instantiating new messages each time, but I've followed what you've done to make it easier for interested folks to follow and compare. Changing messages into structs so they are allocated on the stack and out of arms reach of gc would be one improvement.

http://www.gamesfoundry.com/downloads/EventMessaging.zip

Any speed tests would need to take into account the speed of Reflection on complex classes with lots of properties rather than the extremely simple classes used here.

Darrel Cusey
profile image
Simon,

Thanks for sharing this -- I wish more developers would help each others out like this. Also, Folk Tale (http://www.youtube.com/watch?v=l0tlX3K1IAo&hd=1) looks amazing :)


none
 
Comment: