Observer Pattern

Tran-scripted source:

When you’re building your first game one of the biggest challenges you’re likely to face is how to connect all of the different moving parts together in a way that works for example making an object do


something on its own can be relatively simple but connecting all of the things that happen in your game together without making it confusing to work with can be extremely challenging luckily there’s a solution


in unity it’s possible to create modular connections between scripts and objects by using event based triggers in this video you’ll learn how to use events and delegates actions and unity events the difference between them and


how you can use them to make your game easier to work with so what is event based logic in unity if you’re new to unity then so far you may have only used update to trigger logic which is fine when what you’re


doing happens every frame such as checking for input or moving an object however a lot of the things that happen in your game probably won’t happen that frequently such as losing the game or winning or setting a new high score


meaning that it doesn’t really make sense to keep checking if they’ve happened yet or not instead using event-based logic it’s possible to wait for something to happen and then do something else in response


for example when the player dies there are a number of other actions that will need to be triggered as a result the player might fall down input will need to be disabled the ui might show a message


enemies stop attacking you and the game is restarted to try to manage all of these things from a single script would be extremely difficult if not impossible to do the player health class would need to


access the ui the input controller the scene manager and every enemy that might be trying to attack you and while in smaller projects it might be possible to do it this way tightly connecting scripts like this in most


cases can make a project very difficult to work with so what’s the solution the observer pattern is a software design solution that allows you to connect the functionality of a script to an event in your game it typically works


by allowing observers to subscribe their functions to a subject’s event then when the event is triggered by the subject the observer’s functions are called in response the benefit of this pattern is that it


allows many different scripts and objects to respond to something happening in your game without needing to tightly connect them together observers manage their own connection to the subject’s event meaning that the


subject doesn’t need to know which scripts are going to respond when the event is called all it needs to worry about is calling the event when it happens and if you want to add or remove observers you can without needing to


modify the subject script at all so how could you use the observer pattern in unity one method is by using delegates delegates are essentially function containers while a normal variable holds


a value or reference to a component a delegate stores one or more functions and calls them when the delegate is triggered they work by declaring a delegate template which is simply the type of value the delegate will return


and the type of parameters it’s able to accept then you’ll be able to declare an instance of that delegate type to store and then trigger different functions this works by setting the delegate to a


function which allows you to swap out which method is executed when it’s called or by adding a function to the delegate which allows multiple functions to be called from one trigger methods can be individually removed by


subtracting them from the delegate or the whole delegate can be cleared by simply setting it to null when the delegate is null it’s basically empty and trying to call it will cause an error which is why it’s always important


to check to see if the delicate is null before trying to trigger it but how is all of this useful the basic idea here is that using delegates a single trigger can be used to create different results this creates


abstraction between the thing that is triggering an event and the thing that is responding to it since it’s possible to add swap or change how other scripts react to a trigger without changing the trigger itself which makes it possible


to implement a version of the observer pattern using delegates by making a delegate instance public and static it’s possible for other scripts to subscribe their functions to it this works by adding the function to the


delegate when the object is enabled and subtracting it if it’s disabled which is important for avoiding errors if the observer object is later destroyed for example the player’s health script might call an on death delegate when its


health drops below zero a ui object could subscribe to that delegate to show a game over message when that happens neither object relies on the other to exist and there’s no tight connection between them since the ui object manages


its own reference to the delegate however there are risks involved when using delegates like this the delegate instance needs to be publicly available so that other scripts can subscribe to it but because of that it’s entirely


possible to accidentally set the delegate instead of adding to it which would prevent other functions from being called what’s more there’s nothing to stop any other script from calling the delegate


itself which can cause problems or at the very least be confusing as it will be harder to know which object is the subject and which is the observer this can happen because delegates alone are not an event system they are simply


a method with which to trigger one or more functions of a matching type from a single call which is why if you’re planning on using delegates to implement the observer pattern you may want to use them as event delegates instead


events are a special kind of delegate to turn a regular delegate into an event delegate simply add the event keyword but what does that do generally speaking events work in exactly the same way as delegates except


that while a delegate can be set or called from outside of the class it’s declared in an event delegate can only be called from inside its own class which means that other scripts can only manage their relationship with the event


they can subscribe and unsubscribe their own functions but they can’t trigger the events or alter the subscription of other functions from other classes this makes delegates work more like an event system and while the basic


functionality is the same it makes it much easier to avoid errors since observers are unable to perform the actions of subjects the only drawback of using events and delegates in this way is that you need


to declare the delegate type before you can create an instance of it which might not be a problem for you but there is a way to use basic event delegates without needing to declare them first using actions


actions are basically ready-made delegates they can be used to easily create a delegate or an event delegate with a void return type without needing to separately declare the delegate type to use them you’ll need to add the


system namespace then you’ll be able to create an action instance in the same way as you create a delegate instance except that you won’t have to define the delegate type first other functions can subscribe to the


action in the same way as a regular delegate and the action can be triggered in the same way as well the only thing that’s different is that you won’t need to set it up first while actions don’t return a value they


can accept parameters by passing value types into angle brackets when declaring the action instance this will require you to pass in parameters of the same type when calling the action and will mean the only


functions that accept the same pattern of parameters can be subscribed to it actions are great for creating event delegates in code however what if you want the benefits of an event based system but you want to manage it in the


inspector instead unity events work in a similar way to delegates except that while you’d normally set up delegates in a script unity events allow you to create modular functionality in the inspector instead


chances are you’ve used unity events before as the drag and drop event system that ui buttons and sliders use is based on unity events however while you may be used to seeing them on ui components they can also be used to create modular


connections between scripts this can be extremely useful for setting up different objects in different ways using the same scripts for example imagine that you have a box and an enemy you could use the same script to allow


both objects to take damage and when they run out of health each are destroyed however what happens next might be different for each object for example destroying the box might


drop loot while killing the enemy might give you experience the trigger is the same but the results are different so how does it work to use a unity event you’ll need to add


the unity events namespace then declare a public unity event for the event you want to create and trigger it using the invoke function unlike delegates you won’t need to check to see if the unity event is null before


calling it then in the inspector you can connect the unity event to other scripts and objects either to call a function turn something on or off or do nothing since the advantage of using a unity event


like this is that different objects can do different things with the same trigger when connecting unity event to a function by default unity events pass static parameters


meaning that the value or reference that is given to the function if it takes one is whatever you set in the inspector however it’s also possible to create unity events that pass dynamic data for example a unity event is called


where an object is damaged could also be set up to pass the amount of damage taken as a float this works by creating your own serializable class that inherits from unity event this allows you to create a type of


unity event that accepts up to four parameters by specifying what values the event will take in angled brackets then use your custom unity event in place of a regular one and select the dynamic value option when connecting it


to a script unity events are great for creating modular points of contact that can be used to connect objects together in different ways however because they involve connecting


scripts manually in the inspector they usually work best for interactions between local objects such as scripts on the same object or group of objects within a prefab while static event delegates can be used


in code to manage game-wide global events that affect multiple other objects but what if you wanted to combine the benefits of working with unity events in the inspector with global game-wide events


scriptable object events use unity events to create modular connections between scripts but while unity events work well for connecting objects locally scriptable object events can be used to combine


local connections with game-wide events this works in a similar way to event delegates where observers can subscribe to a subject’s event without needing a specific reference to that object the difference is that by using unity


events it’s possible to customize the observer’s response in the inspector instead of in a script so how does it work scriptable object events work by connecting the subject and the observer


to a common game event which is a scriptable object asset that exists in your project not in the scene this acts as a layer of abstraction between the events and anything that is triggered by it which keeps them


separate and nicely decoupled to make scriptable object events you’ll need two scripts a game event listener and a game event the game event listener is essentially the observer and is a regular script


that is attached to any object that will respond to an event when it happens the listener will subscribe itself to an event and then when it’s called will trigger its own unity event in response which can be manually connected to other


local scripts and objects the game event which is a scriptable object asset contains a list of subscribed listeners and provides functions for a listener to add or remove itself from the event


when the event is called each listener in the list is triggered which invokes the unity events on each one in your subject script to call an event when it happens simply declare a game event and call the trigger event


function because the game event is a scriptable object it exists in the project as an asset in the same way as a material or an audio clip does meaning that it’s possible to create


different game events for different purposes to connect a listener to a specific event all you need to do is make sure that the listener and the script that calls the event you want to connect it


to are both referencing the same game event asset for more on scriptable object game events try ryan hipple’s unite austin talk which i’ve linked in the video description


now i want to hear from you are you using delegates to create events in code or would you rather use unity events to connect objects locally in the inspector or maybe you like the idea of using scriptable object events to get the best


of both worlds whatever it is let me know by leaving a comment like this video if you found it useful and get subscribed for more videos from me i’ll see you next time [Music]


Leave a Reply

Your email address will not be published. Required fields are marked *