In this lecture, we'll re factor our game again to get an even better object oriented design. The big idea is will add an EventManager utility class that will make it so that the game objects in our game don't need to know about each other at all to do event handling. We'll start with a reminder of how our current implementation works. In our Fish class, we have a field that's a PointsAddedEvent. We provide the capability for consumers of the class to add themselves as a listener for the PointsAddedEvent. And when we collide with the teddy bear with the head of the fish, we invoke that PointsAddedEvent providing how many points should be added to the players score in the HUD. In our Start method, we find the fishScript and this is something that will go away, which is great. We find the fishScript and then we add our AddPoints method as a listener for the PointsAddedEvent. So when the PointsAddedEvent is invoked, it calls AddPoints and adds points to the player score and, of course, changes the text in the HUD as well. Let's make it so the HUD doesn't have to know about the Fish. Back in the editor, I'm going to add another script that all call eventManager because it manages events. And I'll open up that script and I'll say this is an EventManager, And it won't inherit from MonoBehavior and it will be a static class. So that makes it so neither the Fish nor the HUD has to get an instance of the EventManager to be able to call its methods, it can just call them as static methods. I'll get rid of the Start and Update methods because we don't get those anymore nor do we need them. So the idea behind this static EventManager classe is, this is a utility class. It's a class that provides helpful functionality to the game objects in the game. So you can think of this like the configuration utilities that we have, that provides configuration data to different game objects in our game. Or the screen utilities that provides information about the screen. So utilities classes are fine. It's fine for the game objects or the scripts for the game objects in our game to know about utilities classes to access that utility functionality. And just not knowing about the other actual game objects in the game. And that's a great way to try to structure our code. There times we can't, but using event systems with an EventManager is one of those times that we actually can. So I'm going to need two fields in this EventManager. I'll have a field for the invoker which I know is a Fish and I'll call it invoker. And I'll have a field for the listener which I know is UnityAction, one int, but I'm not actually getting any help here from intelligence because I need a using directive. And now I can actually have a UnityAction with an int, and I'll just call this Listener. I'm going to add two static methods. And by the way, the reason these fields are static is because my methods are static. So to access fields from within a static method, those fields need to be static. So this will be static void AddEventInvoker and we know it's a Fish and I'll just call it script. I'll add my comment, And as we build more complicated event managers that have different events that they're managing rather than just the PointsAddedEvent, we'll need to come up with better names, like AddPointsAddedEventInvoker instead here. But since we're only dealing with one event, this is fine the way it is. What we do here is we set our static field equal to the script that was passed in. That means we need to come back to our Fish and do a little more work. At the end of our Start method, we'll add self as the event invoker so we can call the EventManager.AddEventInvoker. And you'll see intelligence isn't helping me because, of course, this method needs to be public. And add this, this script, this C Sharp object as the invoker of the event. So now I've told the EventManager from the Fish that I am somebody who invokes the event. One of the great things about using this EventManager is we don't care in which order the invoker and the listener call a method in the EventManager. So could be the case when we call AddEventInvoker, the listener hasn't been added yet and this would be all the code we need. But if the listener has already been added, we want to make sure that we add it as a listener to this invoker that we just added. So the code I'm about to add is for the scenario in which the listener has been hanging around waiting to get added to an invoker. And now that we're adding the invoker, we can add the listener to that invoker. The way we check if the listener has been added or not is we check to see if ( listener != null). I just tapped away because that was just what I wanted to do. So if the listener isn't null, we already have a listener hanging around waiting to be added to an invoker, so we just say invoker.AddPointsAddedEventListener. I'm tabbing away again to actually take the suggestion so we can add the listener as a listener. So we've just handled the situation where the listener was added first. And now that we've added the invoker, we're hooking the listener into the invoker. The AddEventListener script looks a lot like this, so I'll write that code and then we'll come back. Okay, so here's the code for the other side of that connection. It's a public static void method called AddEventListener. And this time the data type for the parameter is UnityAction <int>, and I've called this handler here. You may be wondering why I'm making sure my parameter names are not the same as my field names. It's because I can't actually use this dot to distinguish between a field and a parameter that are the same name if the field is static, because there is no such thing as an instance field called listener. So that's why they're different names. That's fairly subtle, if you didn't even notice and you don't care, that's fine, but that's why I'm doing it that way. So, this first thing I always have to do whether the listener is getting added first or after the invoker. And this code checks to make sure the invoker hasn't been added first and is just hanging around waiting for a listener to say they want to listen. So if the invoker isn't null, we've already added the invoker and we want to add this new listener as well and the listener for the event to the event in the invoker. And that's it for the EventManager. The last piece we need is, I told you here in the HUD, we could get rid of all this stuff and not really all this stuff. We just change this to EventManager instead and change it to AddEventListener. And now, instead of finding the Fish game object and adding our AddPoints method as a listener for the event in the Fish game object, we just tell the EventManager, we care about this particular event. And we don't even have to know who invokes the event. We don't have to know if it was the Fish, we just told the EventManager we care about this particular event. I'll show you that everything compiles fine and when I run the code, hopefully, I can eat a teddy bear quickly and I did. And you can see it works exactly the same way it did before. But now we have a better object oriented design even than last time because the HUD doesn't have to know about the Fish and the Fish doesn't have to know about the HUD. They do both need to know about the EventManager, but the EventManager is a utility class that it's reasonable for our scripts in the game to know about to make the game work properly. To recap, in this lecture, you learned how we can add an EventManager utility class that makes it so our game objects don't need to know about each other at all to do event handling. And this approach leads to a really solid object oriented design.