In this lecture, we'll explore the object pool pattern. So the motivation behind this pattern is that we improve performance in memory usage by reusing objects from a pool instead of allocating and freeing those objects individually. And those terms allocating and freeing sound a lot like C++ terms where we have to manage our own memory. But this applies in the C Sharp domain as well, where we instantiate objects and then when we're done with them, the garbage collector picks them up. The object pool pattern applies in the C sharp domain as well. So, adapted from a Nystrom's description, we defined a pool object that holds these objects that we're going to reuse. When we need one, we asked the pool for it, and when we're done with one, we return it to the pool. Let's go implement the object pool pattern for the French fries in our Feed the Teddies game. Because we're going to pool the French fries in this game, we actually need to make some changes to both the French fries and the burger classes. So, we'll look at those first and then we'll look at the French fries pool. Here in the French fries class, we're going to initialize the object and I used to do this work in start instead of initialize, but I want to initialize the French fries when I'm creating them and putting them in the pool. And if they haven't been added to the scene yet, then start won't get called. So I'm going to call this initialize method explicitly when I instantiate a French fries object. I also used to start the French fries moving in the start method. But now, what we want to do is we want the burger to grab a French fries object from the pool, put it in the place where the burger is, and do any other work it needs to do, and then start the French fries moving. So we needed an explicit method that we could call to actually get the French fries moving. And we want to stop the French fries moving when we actually put them back into the pool. So that the next time the French fries are removed from the pool, they don't have any velocity. Any time we destroy the French fries, instead of actually destroying the game object the French fries script is attached to, which is what we used to do, we're going to return the French fries to the pool instead. So now, French fries will be a reusable object that we can just retrieve from the pool when we need one and then return back to the pool when we're done with it. So, this is a change because we're not destroying the French fries game object, we're returning it to the French fries pool. And that applies in the other places where we used to destroy the French fries as well. And those are the changes to the French fries class. In the burger class, we've removed the prefab for the French fries we used to have. And instead of instantiating that prefab here, Instead, what we do is we get a French fries object from the pool, we move it to where it should be, we set it active because now, the French fries are active in the scene, and we also get that French fries script that's attached to the game object and call our start moving method so that the French fries actually start moving. So those are the changes that we need to make to French fries and burger. Let's actually look at the implementation of the pool itself. We have two fields in this class: we have the prefab that will instantiate, and we have a list of game objects that is the pool of those French fries. We have an initialize method that gets called by our game initializer script, and that happens in the main menu scene. So, we're going to initialize our pool while we're essentially waiting for the player to interact with the menu and that's a good thing. So the first thing we do is we loaded the prefab French fries as a resource. I moved it in the Unity editor to be a resource. And now, I create my pool. And we'll start for demonstration purposes by creating a pool with a capacity of two. So this constructor for a list, we provide the capacity and that keeps us from having to keep growing that list. Remember growing the list is an order n operation. So we want to avoid that. Clearly, two is not the right choice for our pool. So I'll increase that number when I do this in practice, but I want to show you that the pool actually grows, which is also an important thing. Okay, so this for loop, I start at zero, I go up to the capacity of the pool. Notice this is not count because there's nothing in the pool. This is capacity, because I want to completely fill the pool I just created, and I add a French fries object that I get from the GetNewFrenchFries method that we'll look at at the very end. So, this initialize method basically just fills up the pool. The GetFrenchFries method is the method the burger calls when it needs a French fries object to fire. The first thing we check is to see if, in fact, there is something in the pool. Because if the pool is empty, we're going to have to do something else. But if the pool has at least one object in it, then we'll use that object. I'm going to retrieve the object that's at the end of the list, because we know that remove app is a constant time operation if we're moving from the end of the list. And then I return those French fries that used to be at the end of the list that is our pool. If the pool is empty, this is the message we'll see. And of course you, don't keep that in an operational game. But this just to show you how this is working. So, what we're going to do is, we're going to do two things. First, we're going to expand the capacity of the pool. Because we want the pool to be larger now, we know it needed to be larger. And I'm just going to add one to it. And we'll see why in a couple of minutes. But I want to increase the capacity so that if all of those game objects that have been either in the pool before or that we're creating right here are put back into the pool, that we don't have to expand the pool. So again, we're avoiding that order n operation of growing the pool. So, I increase the capacity, and then I return a new French fries object. We're almost to the point where we'll look at that method. The other thing is that when a French fry is destroyed, it returns itself to the pool. And so, this was the method that we saw getting called in the French fries class. We do a number of things. We set the French fries to inactive. That's why we provide false here. So, it's no longer an active game object in the game. We stop the French fries from moving, and we add the French fries back into the pool. And that always gets added to the end of the list. And remember, that will always be constant time because we expanded the capacity as we needed to. So the capacity of the list is always the same as the total number of French fries objects that are in the game. Here's that method I keep talking about. So, we instantiate our prefab, and then we call the initialize method that we already looked at. We set active to false because this is not an active game object. We say, DontDestroyOnLoad, and I will admit that this was a bug that I had to figure out. So remember, game objects are destroyed as you move from scene to scene in the game. And because I was loading up the pool in the main menu, by the time I got to the gameplay scene, all those French fries objects had been nulled out because the engine had destroyed them. So, just as we saw in our game audio source in Feed the Teddies, if we want a game object to persist across scenes, then we call DontDestroyOnLoad on that game object. So, that was an interesting bug to figure out, but luckily, I figured it out, and we return French fries. So, that's the implementation of our French fries pool. I'll show you in action momentarily. But I did want to say, if you google Unity object pool, you may find tutorials that say this approach is wrong, that it is wasteful and time consuming, and what you should do instead is just build a pool of objects, and basically mark those objects as active or not, and when you need a new object in our GetFrenchFries method in this example, then you do a linear search on that list to find an inactive object to return. And that's a bad idea because we know linear search is order n, and so, as our pool gets huge, that search to find an available object takes longer and longer. So, let's look at the complexity of this implementation instead, since I said it's better. We know this is constant time, this is constant time, this is constant time because we're removing from the end of the pool, and this is constant time, this is constant time, this wouldn't be included in our real game. So the only question is, what about this? What about increasing the capacity of the pool? If that's constant time, that's great. Getting an object from the pool is always constant time which is better than order n. If it's not constant time, then we maybe haven't done anything to improve that other approach. Here's the documentation for the List Capacity property. And at first blush, this is not a win because it says here, setting the property is an order an operation where n is the new capacity. So, if in fact that statement is true, then we haven't done anything better than the other approach. This is a little ugly to have to do, but that didn't make sense to me when we're increasing the capacity of an empty list, which is what we're doing. We only execute this code if pool.Count is equal to zero. So when things don't make sense to you given your understanding of how everything works, it's reasonable to explore further. So, it turns out that Microsoft gives us the source code for the list class and if we look at the source code for the capacity property, and we look at the set accessor, and we don't worry about the contract stuff, value, the new capacity, is not equal to the old capacity. That's certainly true. If value is greater than zero, and of course it is in our case, then it creates a new array of the appropriate size which makes perfect sense. Here's the piece that says we don't have to worry if, in fact, count, because they use _size to keep track of count, if that's greater than zero, it does an array copy, and this is where you get order n. But it's really not order n in the capacity, it's order n in how many things are currently in the list. And they made a reasonable assumption when they provided the complexity of this operation in their documentation. They assumed you would only increase capacity when your list was full. And were actually increasing the capacity when our list is empty because we know we need that capacity later. So, this boolean expression, in our case, evaluates to false. So, all that happens is this. So actually, for us, increasing the capacity by one is a constant time operation. So that means that increasing the capacity is constant time for the way we're doing it because we're only doing it on an empty list, which means getting an object from the pool is constant time rather than order n. If we were, in fact, paying our price when we return objects to the pool, then we haven't won over that other approach either, but this is also a constant time. So, setting active is constant time. Stopping moving is constant time. And because we made sure that the capacity is as big as the total number of French fries that are floating around in our game, add is a constant time operation, not order n, which we'd have to pay if we had to expand the list. But we don't have to expand the list, so this is constant time. So, this implementation of an object pool is constant time for getting an object from the pool and returning an object to the pool, and that's better then the order n object pool implementations that you might see as you wander around the web. So, if I play a game, you see, I don't get any messages from my old French fries. But as soon as the third French fry, you can see that [inaudible] and a fourth French fry, and so on. So, of course, you wouldn't include this message in a game that you ship, but I wanted to use it to show you that we actually do grow the pool as we need to as we need more French fries in the game. To recap, in this lecture, we learned about the object pool pattern, and we implemented that pattern for the French fries in our Feed the Teddies game.