In this lecture, we'll refactor our Teddy Bear destruction game to use an event in an event handler. The event manager in this example is more robust than the event manager we saw in the previous lecture because it allows multiple invokers and multiple listeners for the event. Here's a reminder about how the TeddyBearDestruction game works. When I play the game, it spawns teddy bears and when I get the mouse over them, I gain points from destroying the teddy bears. I had to blow one up too. That's how the game works, let's go look at the code. Remember we have a TeddyBearDestruction gameplay manager, if you will, but really this just does what our typical handler does. I have scoreText in the actual score. In start, I set my scoreText to Score followed by a zero. Then I have a public AddPoints method that adds points to the score and changes the text. If I right-click AddPoints and find all references, we can see that all three of the concrete classes, the BurningTeddyBear, DisappearingTeddyBear, and ExplodingTeddyBear, all call the AddPoints method to add point. The parent class in that hierarchy, the Teddy Bear class has a protected field to hold a reference to a TeddyBearDestruction object and that's the object that those child classes are using to call the AddPoints method. The bad part about this design is that the Teddy Bear class has to know about the gameplay manager and we would prefer that it not. We would prefer that the Teddy Bear class just know that it's a Teddy Bear and instead of providing a reference to this gameplay manager object that all the child classes actually use to add points for the player, we would prefer that we could just invoke an event and the TeddyBearDestruction gameplay manager would listen for that event and then the teddy bears don't have to know anything about their place in the bigger game world. Let's refactor this code to use an event and an event manager. I've added two scripts to our game, I've added a PointsAddedEvent in the EventManager. Let's look at the PointsAddedEvent first. As you can see, we inherit from the version of the UnityEvent that has a single parameter, that's an int, and that will be the number of points we want added to our score. Our EventManager is more robust than the EventManager from the previous lecture and that's because we now have a list of TeddyBears as invokers and a list of UnityAction ints as listeners. We know that there are probably more than one Teddy Bear in the game at any particular time and each of those teddy bears can invoke our PointsAddedEvent so we have to have a way to store more than one invoker in our EventManager. A list is a good collection class for us to use to do that. We'll have a list of TeddyBears as our invokers of this event. We actually know that we only have one listener for the event in this particular game, it's the TeddyBearDestruction script but once we have a list for invokers, we might as well just use a list for listeners as well, and vice versa. We can have an event that has a single invoker and multiple listeners so we'd need a list of listeners and it makes sense to have lists for both the invokers and the listeners for a particular event, if we need a list for at least one of them. That's what I've done here. That's an extension of the EventManager that we saw last time because here we can have multiple invokers and multiple listeners for the event. We have two public methods in the EventManager. The first one adds a Teddy Bear as an invoker. The way we start doing that is we add the new Teddy Bear invoker to our list of invokers using the add method. Then just as we needed to do previously, we may have one or more listeners that have already said that they'd like to listen for this event. If we do, we need to add each of those listeners to this invoker as a listener for the event that this invoker may invoke. We don't have to check for null anymore because we're using a list. We can just use a for-each loop that goes across all the listeners that have been added so far and adds each of those listeners to the invoker. You can see I have commented out this line of code at this point so that my code will compile because Teddy Bear at this point doesn't implement an AddListener method. We'll take care of that soon, but we haven't taken care of that yet. The AddListener method looks really similar, this time our parameter is a UnityAction with a single int parameter. We add that handler to our list of listeners. Then we do a for each loop across all the invokers that have added themselves to the EventManager so far and we add that listener to each of the invokers. Again with this commented out code because I haven't implemented this method in the Teddy Bear yet. Speaking of the Teddy Bear, let's go start refactoring the Teddy Bear to support using the EventManager in the PointsAddedEvent. The first thing we'll do is we'll change this field from being a reference to a TeddyBearDestruction object to being a PointsAddedEvent object instead. We need to create a new object for that event at this time as well. By using the standard calling a C Sharp constructor to create this object. In start, we need to change this code, which used to get a reference to the Teddy Bear destruction script. We don't need that anymore, but we do need to tell the event manager that this Teddy Bear is an invoker of the points added event. I'll get rid of this line of code and instead, I'll add myself as an invoker. As I said, I'll add myself as an invoke and the way we do that is by using this keyword, which remember is a reference to this object. I know that the Teddy Bear is an abstract class, so we can't actually make a teddy bear object. But remember all the child classes inherit from Teddy Bear. All the child classes will in fact be executing the Start method and when they do, they'll add themselves as the actual concrete C-sharp object as the invokers to the EventManager. I'd like to uncomment that code that I have in the EventManager. I'm going to come down here and this particular method I'm going to add needs to be public, so I'll add a new region, and it will be public, void, AddListener. Remember we want to add listeners that are unity action with one-int parameter and I'll just call it listener. I'll add my documentation comment before I fill in the body of the method. Here in the body of the method, I'll say points added event and this is a great suggestion. I'll just tap away and say, I want to call the AddListener method that I inherit or that points added event inherits from Unity event with one in parameter, and I'll pass in the parameter that was passed in here to add the listener to my points added event. Now I can come back to the EventManager and get rid of those comments. When I compile, I'm not quite done yet because in each of my child classes, I'm still calling the Teddy Bear destruction add points method, and I can't do that anymore. What I need to do instead is take the points added event and invoke it. Instead of calling a method directly in the Teddy Bear destruction script, I can invoke the event instead. I'll change the burning Teddy Bear to disappearing Teddy Bear in the exploding Teddy Bear to all invoke the event instead. Let's compile and see how this all works. I will freely admit I have deliberately made a mistake because you may make the same mistake. I want to show you the process for recognizing that we made that mistake. If I run the game, I can actually destroy teddy bears, but I don't get points for that anymore. When that happens, there are really two possibilities. Either we're never invoking the event or nobody's listening for the event. I know which of those two the answer is, because we just added code to invoke the event. Let's go to the EventManager and right-click on AddListener and say find all references, which will show us who actually calls the AddListener method, and it turns out that nobody does. Teddy Bear destruction is the class that should. Add as a listener for event, so we're calling a method in the EventManager, and this time it's the AddListener method and we want to add or AddPoints method as a listener for that event. As a matter of fact, now that we've done that, we can actually make AddPoints private rather than public. Because no consumers of the class now call this method directly. I know that the event will call this method directly, but that's because it has a reference to where this method actually lives in memory. It doesn't actually have to use a public method to call it. Our code compiles again just fine. When we come back and play our game this time, I actually get points for destroying teddy bears. Our game behaves exactly the way it did before, but our re-factoring has led to a better object-oriented design, specifically, because the Teddy Bear no longer needs to know about the Teddy Bear destruction class. To recap, in this lecture, you learned how to implement and even more robust EventManager that supports having multiple invokers and multiple listeners for an event.