The Observer Design Pattern

Hello everyone.
I’m thinking of implementing it (naturally…) in my code.
I was thinking of another way to implement it, I wanted to know if it is a valid way, if anyone tried it, any cons/pros?

The Basic Observer
In the game code you set an observer that should get the events from that specific code/class/object.
Once an event happens, it notifies its’ observer, and the observer does its thing (be it manipulate score, achievement, etc…)
But in this case, you have to have a different observer for each class, one for a score system, one for achievements, etc…
I was thinking, why not have one big observer that collects all of the events?

The Big Brother
One observer gets all of the game’s events sent to it.
While the game runs, it checks if it has a stack of events from the last, or the same frame, etc…
For each of them, it checks the sender, and sends the event to the observer that matters.

Now, I can think of a few things that might pose a problem;

  1. The Big Brother might get too many events in its queue, it might cause a slowdown in event management. A score might update too late, causing the game to continue for bit more (in the good case) after it was supposed to end, the game takes a few more seconds to restart or show a menu after the player dies, etc… (Basically, a bottle neck).
  2. I still have to manage a number of different observers. Though in this case, I keep them in one area and do not have to look for them.
  3. There might be a racing condition to insert an event into the queue.

The Final Question
Did someone try this? Maybe it’s the norm? Is there a better way (I doubt there isn’t, I did not use events that much really) to implement an even system?
I’d love to hear feedback, ideas, maybe existing topics that are related?

Thanks for reading!

Totally not an observer pattern. I’ll try to get to the questions, but first some education. The observers in the pattern are basically people watching TV. The observers are subscribed to a channel, but the station has no idea who the observers are. The station just broadcasts a message and is blissfully unaware of whether anyone actually receiving it.
In C#, an object just subscribes a function to an event, and the event gets called as per the routine. The broadcaster has no notion of who the subscribers are, or even that there are subscribers, it just calls the event regardless.

As for the big brother idea, it sounds terrible if for no other reason than you are sticking a middle man in between interactions that are probably meant to be lightweight. I have no idea why you would actually want some kind of arbiter executing or executing (this time in the death panel sense) interactions that are meant to be up to the listener/subscriber (whatever you want to call it). It sounds over-designed and probably far more trouble than it’s actually worth.

5 Likes

@MrPriest : The Big Brother class you are talking about is basically using the Mediator pattern. It is used for exactly the situations you describe. As code base increases and there is more and more communication going on all of this communication code itself can muddy up the class specific code. With the Mediator you make your Big Brother object and all communication goes through this central system. It will collect all of the messages and distribute them to the appropriate places. Basically it is just applying Single Responsibility by running all communication through this Mediator.

However, as @RockoDyne stated the Observer pattern has a different focus. With it the idea is you do not actually use any specific communication class and instead just publish your events. Any other objects can subscribe to receive those events and the object publishing the events has no idea who (or if any) are actually receiving its messages.

You can however, combine the two and this is exactly the method I prefer. I have a NotificationsManager class. It is a singleton. Objects subscribe to various notifications through this class. They also publish to either a specific subscriber or broadcast to all subscribers. This gets me the best of both patterns while getting rid of the downside of both patterns.

1 Like

I see, thank you both for your replies!

I am just working on ideas, I’ll probably try it in a simple chess game project (“Simple” meaning, I don’t have to think of inventing any other aspect of the game, but will still have challenges and learning experience working on it)

Thank you again for your look on things (and fixing my understanding of it)

If you want an example… I have it in my spacepuppy framework available on google-code.

Here is the Notification class:
https://code.google.com/p/spacepuppy-unity-framework/source/browse/trunk/SpacepuppyBase/Notification.cs

You inherit from this Notification class to define a ‘type’ of Notification a script may dispatch. This allows for type safe registering of notifications, and to define any parameters that may come with them (think like how EventArgs are in .Net’s event system).

It also has a group of static methods that take care of preparing GameObjects seamlessly for you. So when you register to listen for or post notifications, you do it through these static methods.

This here is the code that does the actual heavy lifting though:
https://code.google.com/p/spacepuppy-unity-framework/source/browse/trunk/SpacepuppyBase/INotificationDispatcher.cs

I used to have a design where ‘Notification’ was a static class (sort of singleton), and it stored all the relationships of who was listening for what. But as the number of Notifications registered for grew, it got VERY slow. You can see that old version here:
http://jupiterlighthousestudio.com/spacepuppy_unity_framework_and_unity_notification_system/

I wrote an article about it, and it’s now outdated.

This new version attaches a script to those GameObjects that have something registered for it, and that takes care of the work for you, and thusly is much faster. The global registrar is still in ‘Notification’, but that’s just unavoidable.

You’ll notice that everything is actually based around the interface ‘INotificationDispatcher’. And the code doing the lifting isn’t a MonoBehaviour/Component itself, and instead is consumed by a component. This is because I wanted it designed so that even NONE GameObject/Components could also dispatch notifications.

2 Likes

This is interesting.
I much prefer to write things myself, however, I will go over this!
It’s a waste not to learn from anothers past experiences.

Thank you very much!

1 Like

I’d like to understand your motivation but I don’t know what “required”, “dig out a reference”, “entity hierarchy”, and “directly” mean. I don’t know if these are terms you made up, or ones that you think are ubiquitous.

‘required’:
means that the object you attach the listener to (the component that dispatches an event) has to had. You need to know exactly which component is going to send it up, and what about if there are several components? Then you have to register with each component individually.

‘entity hierarchy’:
earlier in this article I mention, and link to, my entity design

Here is the article:
http://jupiterlighthousestudio.com/organizing-a-group-of-gameobjects-in-unity/

‘dig out a reference’:
you have to find the GameObject within the entity hierarchy, then get the components, and individually reference.

‘directly’:
My Notification system allows you to just register a notification listener with the root of the entity, and any and all notifications dispatched from within the entity will be received. With events, you can’t indirectly do this, you have to directly register with each component.

Think of it like unity messages. You don’t need direct references to things. One component sends a message, and all components on the GameObject you send it to receives the message (or in a hierarchy if you use SendMessageUpwards).

This acts like Messages, but in the reverse order, and with type safety (instead of string names).

Here we register with a component, gameobject, or even cluster of gameobjects (entity), to listen for a specific ‘notification’. Then when that object dispatches that notification, it doesn’t care who is listening (observer pattern), it just gets received by all observers.

It seems to me like you’re reinventing the wheel. Static events and indirection through event forwarding* seem to solve the problems you’re talking about, as I understand them.

  • e.g.
abstract class ActionTaker: MonoBehaviour {public event Action takeAction;}
class ChildEntity1: ActionTaker {} class ChildEntity2: ActionTaker {}

class RootEntity: MonoBehaviour {
    public event Action<ActionTaker> takeAction;

    void Awake() {
        foreach (var actionTaker in GetComponentsInChildren<ActionTaker>())
            actionTaker.takeAction += () => takeAction(actionTaker);
    }
}

static event would be for a more global aspect.

This isn’t for globals (though a global option is included, but it’s a minor addition).

I’ll give you an example. All my enemies, players, and even debris and obstacles have the ability to harm. May that harm be they shot a projectile, they have a bump surface (spikes), they swung a sword, they have an AOE (fire, electric field), whatever. They all have scripts that take care of this action, BUT this script may or may not be the same class, or have a consistent interface, or even position in the entities hierarchy. The sword could be in the hand bone of a model, the bump surface a collider right on the root of the entity. We don’t know.

When this script operates that it’s striking something, it needs to inform both the entire entity that this happened, and the entity that it happened. An “OnStrike” notification.

This could be seen as similar to ‘OnCollision’, both the parties involved are sent this message.

So the entity being struck has a script somewhere in its hierarchy (for organizational purposes) that needs to react to this. It needs to receive this message. Also the entity that does the striking has some sound effect that plays on it, and this is done in a different script than the script performing the strike.

So, BOTH entities have a need to listen for this event to occur, but doesn’t know exactly who in each other’s hierarchy is signaling it (especially not the one being struck, since it didn’t do the signaling).

So the play sound effect script registers with its root that it wants to be told about any time it strikes something.

And the got hit reaction script registers with its root that it wants to be told if its been struck.

Then the striking script signals the roots of both its own entity, and the entity it struck, that this occurred. And as a result these observers perform the task desired.

//in sword script
void OnTriggerEnter(Collider other)
{
    //determine if collision is a legite sword strike, calculate damage, strikingEntity, strikingWeapon, and who was struck
   
    var n = new WeaponStruckNotification(damage, strikingEntity, strikingWeapon, struckObject);
    Notification.PostNotification<WeaponStruckNotification>(this, n, true);
    Notification.PostNotification<WeaponStruckNotification>(struckObject, n, true);
}


//in struckObject reaction script
void Start()
{
    Notification.RegisterObserver<WeaponStruckNotification>(this.FindRoot(), this.OnWeaponStruck);
}

void OnWeaponStruck(WeaponStruckNotification n)
{
    this.Health -= n.Damage;

    if(n.StrikingWeapon.HasKnockback)
    {
        //do knockback
    }
}

//in entity that did the striking
void Start()
{
    Notification.RegisterObserver<WeaponStruckNotification>(this.FindRoot(), this.OnWeaponStruck);
}

void OnWeaponStruck(WeaponStruckNotification n)
{
    //play sound effect
}

I wouldn’t say its reinventing the wheel. It’s taking the decouple nature of ‘messages’, and adding the type safe nature of ‘.net events’, and expanding on both by giving it an understanding of my ‘entity hierarchy design’. It’s its own deal that perform a task that I find very useful… static events can’t really do that without some mediator in between handling who receives what messages…

I also have another system in my framework (no source available for this one) that basically allows design time, no code, registering for various events that then trigger some other component I call ‘triggerables’ (it’s oddly a lot like the ‘event’ system unity released in their new UI system, but before I even saw their new UI system). And these Notifications integrate easily with them as well.

Anywho, if you don’t see the benefit of it, that’s fine. Either you don’t need this in your designs, or maybe I’m just not describing it well enough. At the end of the day… I have use for it, someone else might (I’ve seen this design done before, just not as robustly… like here: http://wiki.unity3d.com/index.php?title=NotificationCenter ). Don’t use it.

I merely shared it because OP was talking about basically doing what I had already done. Figured they’d find looking at what I created useful.

2 Likes

I think you put so much work into this that your mind is closed to the idea of it already having been created, an in a more usable way. This is something that happens to humans. It’s not a problem with you if you were ignorant of information; it’s only a problem if you can’t explain to yourself and others why you’re still holding on to beliefs that you can’t rationalize.

Personally, I think your last post is a more complicated way of doing this:

struct WeaponStruckEventArgs {}

abstract class Weapon {
    public event Action<WeaponStruckEventArgs> struck;

    void OnTriggerEnter(Collider other) {
        struck(new WeaponStruckEventArgs());
    }
}
class Sword: Weapon {}

abstract class RespondsToSwordStrike {
    Sword sword; // This can be from your "FindRoot()".
    void Awake() {sword.struck += args => {};}
}
class StruckObject: RespondsToSwordStrike {}
class StrikingkObject: RespondsToSwordStrike {}

I might be totally off-base.

What if there are 100 swords in the scene?

What if some entity needs to listen for when its struck by ANY of those swords?

What about all the other weapons that might exist? The spikes, the fire, there’s LOTS of them. They’re not a ‘Sword’, there’s no ‘Sword’ component to ‘get’ and attach my listener to. I’d have to some abstraction of a weapon (an AbstractWeapon class, or IWeapon interface) that all weapons would have to implement… and STILL I’d have to search for ALL known weapons out there in existence and register with them. What I do when a new enemy spawns, now everyone needs to be informed that this new enemy spawned so it can register with that one as well. And no a ‘static event’ won’t work here, because then we’ll receive the event whenever the sword strikes ANYTHING, not just me.

Of course, the weapon itself could instead signal to some defined class on the thing it struck. But now that requires a ‘signal receiver’ class type on the receiver that it searches for and signals to. This would resolve having to know all known weapons in the scene. BUT, now any time I want to receive this message I have to implement some ‘IWeaponStruck’ interface or something.

OR, you could use the built in Unity ‘Messages’, which allows one object to send a message to another. BUT, this is not type safe and uses strings, which I don’t like.

This takes care of that. It allows sending notifications to and from objects, type safely, and with out tight coupling. Just like unity messages, but a little more robust.

Hey, and guess what, it’s already written! I don’t have to do any work to use it… cause it’s done.

Don’t get me wrong, I still use events. Where events are useful!

Its worth noting that the event system introduced in 4.6 does a lot of this for you out of the box. And it uses real C#, instead of strings to do this.

Its pretty much what @lordofduct wrote, but with the architecture build in for you.

@lordofduct , I can’t help us without example code to assess.

You will never not have to do work. You will enable yourself to go into deeper flow states, wherein you use your code with decreasing conscious effort, with practice, but it will never be done with zero cost from your cognitive resources and time banks. Each person who uses what you’ve created will need to go through this. The less code there is, the more flow is possible.

@Kiwasi , what system are you referring to? I tried the Inspector-based hookups, but they’re set up the same as the SendMessage @lordofduct is talking about, which is to say, you take action on other objects, as opposed to making yourself do something in reaction to a UI event. That’s no way to manage complexity. Things will happen, and you’ll have no idea why. It would be a useful system if it were implemented so that your Game Object’s methods could be assigned to be triggered by an event elsewhere.

1 Like

The EventSystem is far more usable then you are giving credit for. Yes, EventSystem is a replacement for SendMessage. But it does a lot more. You can also dynamically subscribe to listeners, the same as with regular .NET events. As another bonus it uses actual interfaces to make the call, instead of strings. The documentation on the EventSystem is not great as yet, but check out the ExecuteEvents class and the various interfaces provided for the UI. You can (should) also write your own interfaces.

If you needed it you could add a layer of abstraction in the middle to provide for a full blown mediator system.

Jessy, I don’t think you’re understanding what we’re describing.

You mostly seem like a competent developer from what I’ve seen from you around here, you probably have your way of solving problems. I have my ways. You’re attempting to explain why I shouldn’t do it my way… but you aren’t understanding why I do it my way… so, your argument just isn’t getting through to me.

And yes, BoredMormon is right, it’s a LOT like the EventSystem released in 4.6. My partner and I were floored when it came out and he was like, “dude… you use this thing just like we use our existing trigger/notification system.” Only difference is it has 1 or 2 things it does that I don’t, and I have 1 or 2 things I can do that it doesn’t.

I’m not going to spend any more energy attempting to explain it further.

I personally think the EventSystem was a far more significant change then the UI tools in 4.6. It didn’t get anywhere near as much love as it deserves. Even the docs treat it as “This thing we had to do to make the UI work, don’t worry about it”. If you can take the time to work through the docs and figure out how it works it is a very powerful system.

1 Like

True, I did not notice the event upgrade.
GUI is just more attractive for non-coders, and me being somewhat new to Unity, did not go over the entire change log.
Thanks for alerting me to this, though.
I’m not originally a C#, embedded or game programmer so while I program for a while now in the industry, I did not have the need to learn (other than definition) about those patterns, sadly. I truly am thankful for such communities.

Why would anyone do that if, like lordofduct’s system, it doesn’t solve problems that aren’t already solved? It either won’t happen without potential ambassadors like yourself explaining why it does something new and useful, or it won’t happen at all. I’m not a believer, but I’m open to convincing.

A TL;DR blog post isn’t the way to go about this kind of thing. Display an impressive, flashy chunk of functionality, and explain its inner workings later. Hooking up events in the Inspector is like that, except for the part about it not actually solving any problems due to the hookups being backwards.