In this lecture, we'll refactor our Fish Revenge game, again, to get an even better object oriented design. The big idea is that we'll implement an EventManager utility class that will make it so that none of the game objects need to know about each other at all. Let's go see how we can make that happen. Okay, this is the game that we ended with in the previous lecture. Remember, we started the previous lecture with the fish needing to know about the HUD. And we didn't like that because fish really shouldn't know about those kind of game components. So we changed our code so that we used event, and the HUD now has to know about the fish, which is still not totally satisfying, but better than the fish knowing about the HUD. In this lecture, we're going remove the need for the HUD to know about the fish by implementing what I'll call a utility class. It's a class that provides helpful functionality to objects in the game. So you can think of this like the configuration utils class that you're using in the wacky breakout project. This provides utility functionality without really supporting actual game play. The script I'm going to add is called EventManager because it's going to manage events. Just a reminder of the way this currently works. The HUD in its Start method finds the fishScript that's attached to the FishGameObject and then adds its AddPoint method as a listener for the point added event. And the fish, implements an add points added event listener method that lets listeners like the HUD, add event listeners for the event. Here's my template EventManager script provided by Unity, so it's an event manager. And it really isn't an instance of MonoBehavior, this is not a child class of MonoBehavior, so I'll get rid of that. I will make it a static class so that the HUD and the fish will actually both end up calling methods on the EventManager. But we don't want them to need an instance of the EventManager, we can just make this a static class instead. Let me get rid of start and update, because we don't get those anymore, since we're not a child class of moto behavior. I'm going to implement two fields in this EventManager class. I'm going to implement a field hat holds the invoker of the event, and I'm going to add a field that holds the listener for the event. So both of these fields will be static so they're accessible within static methods. One, I actually know is an instance of the fish class and I'll call this the invoker. And the field for the listener is remember, a UnityAction<int> and I'll call that listener. Now, I immediately get a compilation error because I need a using directive. Now I'm going to add two static methods. The first one is public static void and it is called AddInvoker, And this is going to be a Fish script. So I'll add a comment here like so, and all I'll do is I will say that invoker, = script. What this does for us is it's going to let the fish register itself as an invoker here with the EventManager, so the EventManager doesn't have to go look for the Fish object and find the Fish script. The HUD doesn't have to go looking for that object and find the Fish script. The fish knows about its own script. Once it's doing its Start method stuff, it can add itself as an invoker in the EventManager. Let's do that now. So here at the end of the Start method in the fish, add self as event invoker. So we put EventManager.AddInvoker and we can just provide ourselves as that event invoker, and that is this instance of the Fish class. So it's this object right here that is attached to the fish game object as a component. Now one of the nice things about using this EventManager is we don't have to know which order these game objects get added to the game. We're not going to have to care if the HUD gets added first. And if the HUD gets added first, and it tries to add itself as a listener on the fish, that fish isn't in the game yet, so we'll have a problem. So we're going to make it that it doesn't matter whether the invoker is added first or the listener is added first here in the EventManager. So when we go to add an invoker here in the AddInvoker method, we're going to check to see if a listener has already been added, and if a listener has been added, we will add it as a listener on this invoker. In other words, the listener got added first and it's been sitting around waiting to get added to an invoker. Now that we're adding the invoker, we can add that listener to it. We want to make sure we're only doing that if listener isn't null. That's how we can tell whether a listener has already been added. So if the listener isn't null, then we will say invoker.AddPointsAddedEventListenter. And it's that listener that's been hanging around waiting to be added to some invoker of the event. The add listener method is similar. I'll type it in and then we'll come back. We're going to pass in our event handler as the listener. So the first thing we do is we assign our listener field to that, and then we check to see if the invoker isn't null. So in other words, if the invoker has been hanging around, waiting for a listener and if it's not null, then we'll call the method to add the listener for that event. And this is really nice because the HUD doesn't have to know about the fish, the fish doesn't have to know about the HUD. It doesn't even matter in which order they are trying to participate in the event-handling process, the EventManager is sort of the intermediary, if you will, to handle all those details. We've already had the fish, add itself as an invoker. So here in the HUD, for the Start method, we want to add the listener and we can get rid of this stuff. All we have to say is EventManager.AddListener(AddPoints). And I will compile so that I can show that everything compiles okay and I'll run to show that everything still works properly. So if I juggle a teddy bear, if I eat a teddy bear, you can see that the score gets added properly. So it 's still the case that the fish and the HUD need to know about the EventManager so they can add themselves as the invoker and listener, respectively but that's okay. Having our game objects know about utilities is perfectly reasonable and that's what we've implemented here. To recap, in this lecture, we saw how to implement an EventManager utility class so that none of the game objects need to know about each other to implement our event system. And this leads to a really solid object oriented design.