In this lecture, you'll learn how you can implement events and event handling in a small game. This game is called fish revenge because the fish actually eat the bears in this game. And that's not how it usually works out for fish. Let's go take a look. Here's the game that will be playing. And I have a fish that I drive around the screen picking up teddy bears with the head of the fish. So the fish is conceptually eating the teddy bears. And as I eat each teddy bear, I gain 10 points in my score. Let's see how the game works in practice. So I can drive my fish and I can eat a teddy bear or I can push them around. But if I can eat them with my head, I get 10 points and so on and I just keep scoring more points as I eat. Let's take a look at the code to see how this functionality is implemented. We'll start with the HUD class so the HUD has a reference to the scoreText so that we can change the text. And it keeps track of the actual score as an int as well and has a string for the ScorePrefix. So every time we display the score we can put that prefix before how many points the player has. In the Start method, I go find the game object with the scoreText tag and I've tagged to the scoreText object with that tag. And I get the TextMeshProUGUI component attached to that game object. And I can set the text to scorePrefix concatenated with the current score. Which at this point is zero because that's what the score is when I start the game. I also have a public static method called AddPoints that has a single points parameter that says how many points are getting added. And when this method gets called, I add the points to the score and I change the scoreText to show the new score. If I right click AddPoints and say find all references. I can find out that within the fish, I call the HUD AddPoints method with bear points, the number of points the bear is worth here, if in fact, I have collided with the head of the fish. And of course, I destroy the teddy bear when that happens as well. So this is the current implementation. We have a static method in the HUD class that lets consumers of the class AddPoints. And here in the fish, we actually call that static method. What we don't like about this implementation is the fish is just a game object that has fish behavior. It shouldn't know that it fits into a bigger game that has a HUD. It should just know that it's a fish and that it can eat teddy bears. So we want to change this so the fish doesn't have to know that the HUD exists or that it has an AddPoints method. The way we're going to do that is we'll use an event. Remember from the UnityEvent documentation that we have a UnityEvent with no parameters and a unityEvent with one parameter and so on. And this is actually the unityEvent that we want to inherit from because this unityEvent has one parameter and we want to pass how many points we want to add to the score. So this is the version of the UnityEvent we want. And you should notice that it says, if you wish to use a generic unityEvent type, you must override the class type. Which means that we need to define a new class that actually inherits from this class providing between the less than and greater than signs the data type of the information that the event will pass. We'll do that by coming over here to the Unity editor in our scripts folder, we'll create a New C Sharp script and we'll call it PointsAddedEvent and we'll open it up. This is our standard template for a new script. I'll say this is a PointsAddedEvent. But we're not inheriting from mono behavior, we're inheriting from the unityEvent generic that has one parameter. When I start typing unityEvent, though, we don't get auto complete for unityEvent and we can see from the unityEvent documentation that this is a class in the unityEngine.Events name space. And we don't have a using directive for that name space in our PointsAddedEvent class yet, but we can easily fix that, we'll just add that using directive. And now we can get access to unityEvent and this is going to be an int because our points will be just an integer. Because we don't inherit from mono behavior anymore, All of this stuff goes away. Now you might wonder, so we have a class called PointsAddedEvent but it doesn't have any methods. So how is this useful? But it inherits from unityEvent. And unityEvent has some useful methods that will use to hook everything together to set it up so that we have a class that invokes the event and a class that listens from the event. The class that invokes the event is the Fish class. So I know I'm going to need a using directive for UnityEngine.Events. And the way I do this is, this is still a score support but I need an object that's a PointsAddedEvent object. So PointsAddedEvent and PointsAddedEvent is a new class that we've just defined. So this is a data type, we just provide the name of the variable or field in this case. And this is one of those cases where we're using pure C Sharp to get a reference to a PointsAddedEvent object. So we call a constructor for PointsAddedEvent, and I'm just hitting tab to complete the rest of this. Okay, so we have this PointsAddedEvent field, we're going to have to do two things with the field. We're going to need to change our code somewhere so that we actually invoke this event. But before we do that, we're going to change our code to make it so that a consumer of this class can actually add a method, a unity action delegate as a listener for this particular event. So I'll go add some of that code and we'll come back. Here's the method I added. So it's public because a consumer of the class external to the class needs to be able to access it, it returns void. I called it AddPointsAddedEventListener as the method name and it has a single parameter, UnityAction<int> and the parameter name. So this data type has to match the event that we defined in the event that we defined, has one int parameter. So this does match the delegate for a listener for that kind of event. Now I need to actually add it as a listener to our event field. So I say pointsAddedEvent, and as I said, we inherit some methods from UnityEvent and it turns out that AddListener is the one we want, and in fact this is a great suggestion. So I'll just tab and take it all. So we're not invoking the event from this class yet, but we are making it so the HUD can add itself as a listener. So over here in the HUD, in our Start method, add self as points added event listener. The first thing we need to do to be able to do that is get access to the script that's attached to the fish game object. So that's data type Fish, I'll call it fishScript. So first, we find the object that is tagged with the fish tag. And I had to go back and add a Ufish tag to the fish but I know I called it Fish. And if we do this, we're holding a game object so now we can get the fish component that's attached to that game object. So at this point I'm holding a reference to the fishScript. So I can call the AddPointsAddedEventListener and I'm going to add AddPoints as that listener. The compiler is letting me do that but we can clean up AddPoints a little bit here because it no longer needs to be static. Nobody external to this class will be calling this method directly. And really that's it for cleaning up the AddPoints method. But once we do that, we can actually come up here and make our scoreText not be static anymore and we can make our int be static anymore. Those had to be static because we were accessing them from within a static method, the AddPoints method when it was static. But since that method isn't static anymore, we can just now make those instance fields or instance variables instead. So we'll try to compile at this point. And we've discovered over in our fish class that we can't call the HUD.AddPoints method anymore because it's no longer a static method. And that's okay, we didn't want to call it anymore anyway, what we wanted to do was invoke our event. So I'll get rid of this And it turns out that one of the other methods that we inherit from UnityEvent is the Invoke method. And we know we said we would provide one integer argument when we invoke the event and that is still bearPoints. So now I can compile successfully. When I come back to the game and play it again, we can see it works exactly the way it did before. Let's see if I can actually eat that fish and I did and the points get added. But it's not because the fish called the HUD AddPoints static method, it's because the fish invoked an event that the HUD was listening for. Let's actually take a couple of minutes and use the debuger to watch the sequence of things that happens when the event is invoked. So I'll set a breakpoint here where I'm invoking the event and in the HUD, I'm going to set a breakpoint here and I might as well come back to the fish and add a breakpoint where I'm adding the listener as well. So when I attach to Unity and run my game, we immediately hit this breakpoint in the fish and I'll step because it was getting called here in the Start method of the HUD. So the HUD is being added to the scene and it's doing all the stuff in its Start method and it called the AddPointsAddedEventListener method. And added the AddPoints method as a listener for the PointsAddedEvent. So now we've hooked the AddPoints listener method into the event. And if I keep running the game and hopefully I can eat a teddy bear quickly. We can see that the fish detected a collision with the head of the fish and the teddy bear so it's invoking the event. And if I step into this, you see that it's calling the listener that registered itself to hear the event, so it called this listener. In this particular example, we only have one listener, but we could certainly have multiple listeners for particular events and the event will call each of them. It will call every single one of the listener methods that have said they care about this particular event when the event is invoked. So I can just F5 now, of course, I get to this break point and then we come back to our game. Now the more astute learner may say, well, you made it. So the fish doesn't have to know about the HUD anymore but the HUD now has to know about the fish. So how is that a win? Well that's kind of true. It's okay for the HUD, which is sort of a game level thing to know about the game objects in the game. That's better than the game objects having to know about the HUD. But we'll actually fix this in the next lecture where I add something called an event manager. So that the fish doesn't have to know about any of the game objects in the game and the HUD doesn't have to know about any of the game objects in the game either. But the good thing from this particular lecture is that we replaced that static method and the fish having to know about the HUD with our first event that we add a listener to and invoke to keep the same functionality, but with a better object oriented design. To recap, in this lecture, you saw how we could re factor a static method that let the HUD add points to the score to use an event and an event handler instead. And this is a better object oriented design, but it's not great, but you shouldn't worry because we'll do better in the next lecture.