Observer Pattern In Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to learn about the observer pattern and how we can use it inside of our games now this is one of my favorite patterns just because it's extremely simple and will change the way that you organize a lot of your code and we'll talk about why in a second the observer pattern can most easily be described as having a subject and an observer now your subject is going to be the event or the thing that holds the event and when i say event this could this could be literally anything inside of your game it could be the player takes damage it could be the start of the level it could be an enemy died it could be the cut scene was triggered if you can point to a single thing that happens in the level that could be an event that you could use in this pattern so you're going to have a class and you're going to have an event or a thing that happens and then you're going to have things inside of your level that want to know when a thing happens so these things inside of your level are going to watch this event and whenever this event happens and this event gets invoked all of the observers that are watching it will get notified and activate a method in reaction to that event so for example you could imagine if a cutscene started playing or let's say a cutscene ends right you have your opening cutscene and you want to do some things let's say opening cut scene ended could be your event and you may have the player input you may want the player to be locked out of input but as soon as the cutscene ended happens your player input could be notified and say okay now i want to allow the player to move or okay i want to change the camera back to its position or okay i want to spawn the enemies in the level the key point of the pattern is just you have a single thing that happens and the observers are notified when that thing happens and they can respond to it to go just one level deeper if you were to think about the code behind this at least in terms of c sharp our subject will have an event and this will be the thing that happens and at some point we need to determine when that event has actually happened and we need you know that's just going to depend on the event but as soon as we put in code when that thing happens we tell the event to invoke and send out its notification so we'll say thing happened dot invoke now all of our observers are looking at this event right here they're at some point they hook in to the thing happened event and they add their method that they want to respond with so this observer might look at thing happened and say okay add my method to the list of things that will respond when thing happens conceptually the observers are looking at the event doing their hookup to the method that they want to respond and then at some point whenever the event happens this will happen when the event happens this will happen the event happens and this will happen that's a little bit of what it would look like inside of code so now as for our specific example we're going to look at a damage system and on our damage system to give a little context to these previously generic boxes we may have a health system that has an event for when the player is damaged so when this thing is damaged we are we want to send out the notification but we are also going to optionally provide and amount the number by which this thing was damaged and just to show you that you could do that and so on the health script we may have a method called take damage and if anything wants to apply damage to the health do this thing with health on it they will have to say health dot take damage they'll send in an amount and then this health script tells the damaged event to send out the notification with the amount that was taken it will also keep track of its own health whatever you can see that and then all these different things inside the level may want to look and say when this thing is damaged i need to respond by doing something so in the case of the target it's going to update its health slider its visual hud in the case of the hit text pop-up we want to see the damage numbers pop up at the top and in the case of our play sound script we whenever this thing takes damage we want to play a sound effect it's important to note that each of these level objects they don't know anything about each other this is a one-way dependency the target does know about the health because it needs to go into this event but the target does not really know about the hit text pop-up which is kind of nice we can make these isolated classes that you know we have this dependency here but we're not creating this weird spaghetti code of everything being connected we are just each hooking into the health individually which is kind of nice way to separate out your code now let's look at our observer pattern in action inside of unity so i have an example project here i'm going to hit play just so you can see what's already set up and we have our canon and we have a target and we have a few other things going on that you'll see like a health bar and so forth if we hit the space bar we're going to fire a projectile and you'll see that when it collides with this target a few things happen we have some text pop up to display the amount of damage we have our health bar gradually decrease we hear a sound effect and overall the structure of our example is going to be one that we have our health script on the thing that's colliding with the projectile and is sending out the notification for other things that care whenever the projectile makes impact and causes damage so let's see how this is set up again i'm not going to go through every single script inside of this example but i do want to touch on the parts that are relevant to the pattern so first we have our standard canon um this isn't relevant to the pattern but just to give you an idea we hit the space bar we are just firing a projectile the projectile is getting instantiated and then flying towards in the forward direction and our projectile is a [Music] it is a prefab here that has a projectile script on it and then some other things that make it work and on our projectile script we have a travel speed and damage and all these other things but what's most important is our right here on collision enter if we collide with something with health we are going to apply damage now the reason this is important is because our health script is the thing that has our event so this is what is the catalyst for calling our damage event so in our scene our target right here has health and on our health script we have an event that says when damage happens this this action event here when we invoke this event we are going to let anything else that is watching this event know and they can respond so anytime this health script takes damage we're calling damage dot invoke right here and we're passing the amount if we're out of health we are you know going to kill and sending out a killed event but we're going to primarily worry about this one right here damaged dot invoke right here so if other objects observe and subscribe to this damaged event then whenever this thing gets invoked they will know about it and they will respond however they need to so for example let's look at the target now the target has a script that just syncs in with the hub and inside of the target which is controlling the health slider on enable so when when this thing is active when the script is active on enable we are subscribing to the damaged event and saying when this damaged event happens we want to add the ontake damage method to be called and response so the process of adding this to the events we'll call that when that notification happens and on disable we are removing this method right here from the damaged event notifications and another way that you'll hear that described as subscribing to the event and unsubscribing which is also the same as watching or no longer watching or whatever so we will typically do that in on enable and on disable so anyways when this event notification happens we will adjust the slider value because we are doing this in response save that and you can see that happening in response to the damage our slider goes down now we have another thing that's happening inside of the level is our hit text that pops up at the top of the screen that is just a text pop-up right here and the way that we're getting that is our hit text pop-up script on our canvas object we're doing the same thing as long as we can get a reference to the health subject that we want to start watching and that's specifically the health component inside of our scene that we want to watch that's sending out these notifications so um we will have to give it the reference to this right here right this is the thing with the health we're just dragging that object instance right there so we are watching that health component on that object and inside of here we're going to subscribe this to this one a little bit differently just to show you that it doesn't have to be in on enable and on disable we're just making a method here just called start observing and we'll give it the health and at any point in time we want to start observing all we need to do is run this code right here which is plus equals so we're getting a reference to the event and in the health and this is the one that we're passing in if we get a reference to that event we start watching it by adding a reference to the method we want to respond with and then at some point when we want to stop observing we just make sure to remove it now if we add it and we don't remove it we run the risk of some lingering dependencies because you know we never stopped watching it and there's a reference that it's creating there just be aware that it's good practice to stop observing whenever you no longer want this object to be active so anyways that's how that is responding and also keep in mind that our hit text popup this cl this object doesn't really know anything about our target that we looked at previously it knows about the health and we're creating the dependency between the hit text pop-up and the health but we are not creating a dependency between the hit text pop-up and the target or you know when we go through the example to play sound and this is really useful because we're not creating a lot of weird connections between all our different scripts we're just creating a connection where it needs to be which is between the observer and the subject so that's important to realize here and lastly we're playing some sound effects and let's look at our script there inside of our level we have this play sound on damage script which you know as long as we can get a reference to the location of the place to play the sound or if you're playing it 2d that's fine too but just to show you another example you can break out the observer scripts as many times as you need to because the only dependency is between this script the observer and the health so inside of this play sound on damage script we have the sounds that we want to play and then we need to give it a location to play at since we're using 3d space but this script is pretty simple as long as we get a reference to the health script on enable we start observing so we add our method to the list of notifications when the health sorry when the damaged event gets invoked we we are going to add that on in on enable and we're going to remove it and on disable we're going to do the same thing with killed and oscar move killed on disable and when this event happens this will will get a callback it's called a callback and we'll get a callback to this method and it will run and response so in this case we're getting the amount of damage and we're not really doing anything with the amount of damage here it's nice that we get it but we could theoretically we could play different sound effects if the damage is above or below a certain threshold for example like a critical hit or something um you could do that if you want but in this case we're just saying when we get the notification if we have build in our references then play the sound same thing with on kill so again those are three different places that are accessing the health event the damaged event but none of those three things the observers so our text pop-up hud or our sound effects our target they don't know about each other they only know about the health script so it's just a really really handy way of creating that one-way dependency and it's also nice because you're not checking for if a boolean has changed an update you're just waiting and getting the notification for the exact moment a thing has changed so just one last final show the projectile triggers the damaged event the damaged event sends out the notifications then everything that is subscribed to the damaged event or the killed event or whatever gets notified and responds by running a method so our hud is now independent and not dependent upon any of the other things in the level our hud is independent is independent of everything except for the health uh our sound effect doesn't know about the hud our sound effect just responds to the health damaged event and our hit our hit text pop-up doesn't even know about the hud down here just knows about the health event that it's watching super super handy way of breaking out your observers and your different classes into fewer dependencies and just watching the thing that it needs to watch and keeping things very simple and compact and only responding when it needs to so very very handy pattern you'll see the observer pattern used a lot inside of ui in particular anytime you have a hud element that's responding to game events very useful pattern but you'll see this pattern all over the place anytime you have an event happen inside of your level that other things may need to react to you probably want to look towards the observer pattern
Info
Channel: ACDev
Views: 2,417
Rating: undefined out of 5
Keywords:
Id: w3ejdCagDIA
Channel Id: undefined
Length: 15min 50sec (950 seconds)
Published: Sun Jan 03 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.