In this lecture, you'll see how a teddy bear can collect things using TArray's of course. Let's go take a look. We'll start by talking about how the game actually works and then we'll look at how it's implemented. When I run the game, I have Ted the collector here. I can right-click in the game world to place a pickup for Ted to collect. I can place multiple pickups along the way as many as I want. But when I left-click, Ted will collect the pickups in the order in which they were placed. Ted will always pick the oldest pickup first. You can see Ted just passes right over other pickups. I can start him collecting and then add more, and he'll keep going. But once he's collected all the pickups in the game, he stops and waits for another left-click to start collecting again. We have a number of C++ classes here, we have a class for the pickup. I did that not because a pickup has behavior, but because I wanted to create a blueprint from that pickup. I have a pawn and a player controller for Ted, and I have a custom game mode that I've used to set up the pawn and the player controller in the ways you've seen me do that before. In our content, you can see I have the blueprint for the pickup, the blueprint for the pawn, and the blueprint for the player controller. Now there is some configuration stuff that I had to do for collisions to make sure that collisions worked properly. In other words, I didn't want a physical collision between Ted and the pickups. I wanted Ted to be able to pass over them and trigger when Ted overlaps with one of those pickups so that I could either ignore that overlap or I could say, "Oh, this is the target pickup that I was trying to pick up." To do that in the pickup, the Static Mesh for the pickup, I needed to set up a custom collision preset, enable collisions, and I marked this object as WorldStatic, and I have it so it blocks physics bodies and Ted is a physics body, and very importantly, I checked this box that says, "Generate Overlap Events." So when an event occurs, I want the engine to tell me that that happened and we have to click that box to make that happen. The other thing I had to do is, in the static mesh for the pawn, I also had to click that "Generate Overlap Events" custom again. I am a physics body and I said I want to overlap with WorldStatic object. Those are configuration things that I had to do to make it so that the engine would tell me when the Ted pawn overlaps with a pickup. Let's go take a look at all the C++ code that I wrote to make this game work. In the player controller header file, I declared a property so that I could populate in the editor, the pickup so that when I right-click, I will place a pickup. This is the actor that I'm going to place when I right-click. I'm setting up my input component as you've seen me do before with the player controllers. I've a PlacePickup function so that I place a pickup on particular input, specifically a right-click. I collect pickups on a left click, and I destroy a given pickup. When the pawn tells me, I run into the target pickup, the pawn will call this function so that I can destroy it and take it out of the TArray. I wanted to do this particular game in this lecture so that we could use a TArray to maintain our set of pickups that we've placed and because we will add our pickups to the end of the TArray, the ordering in the TArray, the front of the TArray, the element at index zero is the oldest pickup. So that will be the target. I want to point out that I didn't mention this when we were talking about two arrays in the previous lecture. But it's very important if you have a TArray field that you mark it with the UPROPERTY macro, so that the engine does appropriate garbage collection. It's not because like we did up here, so we could edit it in the editor or anything like that, it's to make sure that garbage collection works properly on this TArray. So if you're ever declaring a TArray field, you need to mark it as UPROPERTY. I also have this Boolean that tells whether or not we're collecting and when the game starts, we're not, and I have one more function that tells Ted to go to the next pickup, and we'll see how that all works in a moment. In the implementation file, I've set up two Action Mappings. I set up one for PlacePickup with the right mouse button, and we'll respond when that is released, and we'll place a pickup, and I defined another one called CollectPickups, that responds to the left mouse button being released, and we'll call the CollectPickups function. How do we place a pickup? Well, we figure out where the mouse is because we went to place the pickup where the mouse's right now, and remember we use this when we were doing mouse input to make our character follow the mouse. This is how we figured out the world location of the mouse position, setting x to zero, so we stay in the YZ plane. I'm using spawn actor here just like our spawners have used to spawn a pickup, specifically the one we populated in the editor at this world location, not rotated. Now previously when we used spawn actor, we just had this, but this function actually returns a pointer to the pickup that got spawned, and we need that because we want to include it in our, I said list of pickups here, but it's really our TArray, the TArray and we've added this new pickup that we just spawned into the world, and the add function adds this pointer to a pickup at the end of our TArray. That's what keeps our TArray in chronological order, where the front is the oldest and the back is the newest. When we left-click, so this function gets called. If we're already collecting, we just ignore it. We say, okay, well, I'm already collecting so I don't care that you left-clicked. But if I wasn't collecting on a left-click, I go to the next pickup, and here's how I go to the next pickup. If there's at least one pickup in our pickups TArray, so the num function tells us how many elements are in the TArray right now. I get the target pickup. We know it at index zero and I put it into a local variable, and remember this is a pointer to a pickup actor, not the actual actor. Then I remove this pickup from the TArray, and the RemoveAt function lets us provide an index and it will remove the element that's at that index. First, we have to grab it and save it, and then we take it out of the TArray, because we don't want it in that set of pickups that we still need to go pickup. Once we've done that, we get our pawn that we're controlling, and as long as it's not a null pointer, we tell our pawn to go to that target pickup and we'll take a look at that when we start looking at the pawn. Here's where we called go to next pickup. The other thing is when the pawn reaches the target pickup, it calls this function to say destroy it, and we need it to happen that way because the player controller is maintaining our TArray of pickups. It has to know when the pawn has reached the target pickup. The pickup gets passed in and we remove it from our TArray, and we destroy it out of the game world, and now we know there may be more pickups that had been placed in the world, so we want to go to the next one, and we already looked at that go to next pickup function. That's it for the player controller. For the pawn. We need a reference to the StaticMeshComponent for the pawn, because we're going to push the pawn toward a pickup and to use the physics engine to add an impulse, we need the static mesh. I'm saving it here in a field so that we don't have to go get it every time the pawn is sent to another pickup. That's an efficiency thing. We have the typical constructor and begin play and tick. Here's the GoToPickup that the player controller calls in the pawn when it's supposed to go to a pickup and it passes the TargetPickup into the pawn. This function right here is going to act as what's called a delegate for when we get an overlap between a pickup and the pawn. Unfortunately, there's lots of stuff we need to know all at once before we can do interesting things. But just trust me, and I'll talk through a little bit about how this works. But I promise you we'll actually be talking about delegates in much more detail in the last course in the specialization. I have a constant, for the magnitude of the force I'm going to apply to the pawn when I get it moving. I have a TargetPickup that I'm going to save and we'll see why. But I've saved it as a field so that it persists in the pawn as time passes because we'll need that to detect when we get an overlap, whether we're overlapping with the target pickup or not. Then finally, a utility function to get the force vector between two locations. Because when we need to go to a pickup, we need to figure out the direction and the magnitude of the force to apply to the pawn's static mesh to do that, and this function helps us with that job. In the implementation file for the TedPawn. In BeginPlay, this is where I'm saving the static mesh component. Here's a TArray, just because we need a TArray as our argument here, forget components. Basically what we're saying is we're going to have a TArray of pointers to all the static mesh components that are attached to the pawn. Then we call the GetComponents function with StaticMeshComponents to populate StaticMeshComponents. When we get to line 30, static mesh components is a TArray that has zero or more static mesh component pointers in it. We check to make sure there's at least one. If there is, we take it and we save it into our field. Remember, we're doing all of this work because the StaticMeshComponent is the thing that will add a force to, to actually get our pawn moving. This is the delegate thing. Our StaticMeshComponent, we're saying when the OnComponentBeginOverlap event occurs. We've just entered an overlap on this frame with the static mesh component for the pawn and something else. We say call this OnOverlapBegin function that we wrote. We've seen this sort of thing before when we've bound functions to be called when input is provided. This is the same idea. It's just a little more complicated, and like I said, we'll discuss this in much more detail in a couple of more courses. Here's that OnOverlapBegin. Here's what I do. The parameter that I care about, if this function gets called, is the OtherActor, the thing that the pawn is overlapping with. First of all, I just make sure there's no error in the way this function has been called, and then I check to see if the other actor is the TargetPickup. If it isn't, I'm all done. I don't have to do anything. I just keep moving along my velocity vector the way I was before. This is not the pickup you're looking for. But if it is the target pickup, I want to stop the pawn. I do that by calling the setAllPhysicsLinearVelocity function to zero. As you can imagine, I'm setting linear velocity to zero, so that means stopped. I also do that on the StaticMeshComponent. We're applying these physics things to the StaticMeshComponent. The other thing I do is I get to the thing that's controlling me right now. We haven't seen this before, but it's similar to the GetPawn from the controller side. This is from the pawn saying, who is possessing me right now? Making sure that we get the TedPlayerController. If we do, we call the DestroyPickup function with the target pickup, the one we're looking for. Then as we saw, the TedPlayerController removes that pickup from our TRA and destroys it in the world and then moves on to the next pickup. The go-to pickup function. We save the pickup that gets passed in as a parameter into our target pickup field. Then we get the force vector from the pawn, get actor location and the location of our target pickup. That gives us the force vector, and then we add an impulse. This is an impulse force. Think of it as lacking the pawn with a baseball bat or something. It will whack the pawn with a baseball bat. It will add an impulse force in the direction of the force vector with the magnitude of the force vector. Finally, that last function I was talking about, the get force vector. We simply subtract TedLocation from Pickuplocation, so that gives us a direction. But the direction has a magnitude that is based on how far away the pickup is from the pawn,. The Pythagorean theorem tells us that the magnitude of this direction vector will be dependent on the distance. What we do is we normalize the direction vector, so it is a pure direction vector. When we normalize a vector, we give it a length of 1. No matter what direction it's pointing in, its length is 1. But it's pointing from the pawn to the pickup. Then finally, we return that unit vector multiplied by force magnitude, and that's the force vector that we want to apply. I know that's a lot of code and a lot of new stuff, but this is a really good way to implement the game as I showed you. Before I finish, I'm going to show you a flaw in the game. I probably shouldn't, but I will. Back in the editor, if I run the game, a place to pickups really close to each other. Watch what happens when the teddy bear goes. He just leaves and never picks up the next pickup. The issue is that the on begin overlap event happens on the beginning of an overlap. But when we ended up hitting that first pickup, we were already overlapping with the second pickup, so the event was never fired, so we couldn't pick it up. There's certainly a way to solve this problem. We can take a particular actor like the pawn, and we can find out all the actors we're currently overlapping with. When we're told to go to a next pickup, we could actually check to see if we're already overlapping with the target pickup. If we are, we could immediately tell the player controller, "Okay, destroy the next one. I'm already there." That was more complexity than I wanted to add because I think we have enough complexity as it is in this game, but that's also a solvable problem. To recap. In this lecture, you saw how we can use T-Arrays in a small game.