Understanding the Observer Pattern — Event Systems in Unity
I just like using Event Systems!
Ever since I got into game development, there has been a ton of topics to learn, be it 2D art, animation, 3D modelling, programming in C#, getting familiar with the Unity engine etc — it is just overwhelming. But as overwhelming as it may seem, the learning part definitely is my favourite part and since I came from the programming background, I dived head first into picking up the necessary topics for me to build my game Night at the Clownville. Today, I want to share a programming design pattern commonly used in Unity and it is one that I seem to always go back to because of its simplicity. Enter the Observer pattern.
Basically, the Observer pattern is a design pattern that lets you configure a subscription mechanism for subjects to notify multiple objects about any events that happen to the object they are observing.
How it works
To explain the Observer pattern, think about this scenario: Suppose you are waiting for your local store to restock some PS5s (I assume you are still waiting for yours), and you would drive to the store every day or so to check in on the product. While you may be the first on any day to get your PS5, most of the trips would seem pointless if you had no idea whether the store had the product that day. The store could also send you a ton of emails to notify you about the other Sony products that they have in-store, but they are essentially not the products you want. Now, it looks bad to both the store and yourself as a customer.
What the store can do now to solve this situation is to put on a subscription service whereby customers can subscribe to notifications of specific products availability, or commonly called events. Here, the store would act as the publisher, while the customers would be the subscribers. Clearly, customers who are not interested in the PS5s would not subscribe to this event. As a result, the customers need not waste precious resources on unnecessary trips to the store and the store could retain customers by simplifying their lives.
Of course, you would have already known this whole thing already if you live on the internet. YouTube, the biggest video platform ever, would have you subscribe to creators and the moment they publish a new video, you will be notified. Now that we know how this thing works, let’s see how we can implement this using code in Unity.
And yes, if you are wondering, you absolutely guessed it right — there could be multiple publishers and countless subscribers and this would result in a disaster if the network of subscribers-publishers is not maintained properly. Then, you may also have publishers that keep broadcasting event states but with no subscribers listening to them. To make things worse, each publisher may also have a different type of message or information that they want to convey to their subscribers, hence it would be complicated to handle the communication this way. Now that you understand the problem, let’s see what the solution is.
What we want to code in Unity is a game event component that handles the passing of information or message from the publisher. Remember we mentioned the problem of each publisher wanting to broadcast different type of messages? One way to handle that is to create a specific node or message type and let the subscribers know that this node broadcasts this specific type of message and they can subscribe to it if they want to. In short, think of YouTube having this subscription structure where you can subscribe to a creator’s videos, or posts, or articles SEPARATELY. Ideally, you wouldn’t do that, but just imagine it as this is useful in making games.
To create this system, we need 2 components: a game event and a game event listener. A game event component can be called by any game object and is responsible for raising a game event. A game event listener, on the other hand, can be attached to any game object and is responsible for listening to any game events broadcasted by the game object it is subscribed to. To make things modular, we create an abstract class for the game event component that can take in a generic type of message, like this:
As shown above, the Raise() method broadcasts the event to the subscribers. Any response to the event will be handled by the game event listener component — Single Responsibility Principle (SRP). Both the RegisterListener() and UnregisterListener() methods do exactly those when a subscriber decides to listen in on the game event.
For the game event listener, we also want to make it modular with an abstract class.
When any game object with this game event listener component notices that the event is raised, it can invoke a specific set of actions using the method OnEventRaised(). Unity has simplified this for game developers as we only need to pass in a function as a response in the Unity Editor whenever an event is raised and noticed.
Now that we have created a base template, we can go on and make our own specific type of game event messages! Common game event messages type include integer, float or even Unity’s Collider type.
Let’s take a look at a simple example on how I use this event system in my game. Suppose I have coded a PlayerCoinSystem that handles the interaction with in-game coins. As you can see below, this component has 3 events attached to it and can raise any of the 3 events. When a coin is collected, a specific event will be raised and you get the idea for the other events!
On the other end, I have this event listener of integer type attached to the UI component. It listens for the event of OnCoinChange and updates the UI accordingly!
I believe I don’t have to run my game in order for you to understand event systems at this point! Try it out and see for yourself and I’m sure you will fall in love with this pattern!
I have shared how we can write our own game event and game event listener component in Unity using C# and how they can be used basically anywhere in your game. While the code base for Night at the Clownville is currently private, I have an urge to share it with anyone who’s interested in helping us improve the current code base. Email me if you are interested! Until then, happy coding!
Also known as: Event-Subscriber, Listener Observer is a behavioral design pattern that lets you define a subscription…
Design Patterns - Observer Pattern
Observer pattern is used when there is one-to-many relationship between objects such as if one object is modified, its…