How to do Object Pooling [Unity Tutorial]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi guys mike here from comf3 interactive welcome back to the channel today we're going to be taking a look at object pooling now the main purpose of object pooling is so we don't actually need to instantiate and destroy objects at runtime or at least not as many as we usually do and the reason that's a good thing is instantiate and destroy your particularly heavy commands so in certain games such as enter the gungeon this is what's known as a bullet hell game and as you can see by the gameplay on screen there are hundreds if not thousands of bullets being shot every couple of seconds so if we to do this in our games using instantiate and destroy we would take a huge performance hit so the way that games like this do it is through object pooling and i'm going to try and make this as simple as possible because it can get a little bit advanced you could expand on the final product but essentially what we're going to want to do we're going to want to change what's happening currently which as you can see over here in the hierarchy every time one of these bullets spawns it's just spawning in down at the bottom moving upwards when it hits my wall collider it's being destroyed but that is actually gonna be very detrimental to our game we don't need to do this as you can see we only ever really have a finite number of bullets on screen at once so there's no sense in creating a new one every time we want to spawn one and by the end of the video it's going to look something like this just let me swap my chord out really quick you know if you keep your eye on the hierarchy everything will look the same in the game view but take a look at the hierarchy if i expand these and carry on we see we never have more than this set number of bullets which is going to be giving our game a lot better performance and the good thing about the system i'm going to show you how to make is it'll work on any prefab whatsoever so you'll be able to pool bullets pickups anything like that they're all going to be giving their own individual pool and also if we don't have an object that's ready to go we're just going to create a new one on the fly so we will be doing a little bit of instantiation but we'll never be destroying anything so enough of me talking about it let me show you how it's done but first i just want to thank gigatank 3000 for sponsoring this video go check him out on twitter and on his website i've got links in the description below and go and keep track of his latest game that he's got in development and i also want to thank everyone over on patreon you guys are fantastic okay so let me just show you the way that you're probably going to be doing this kind of spawning in your game already so we take a look at our bullet spawner we just have some basic input controls over here but this is the important line so every time we want to shoot we're in using the instantiate command we're instantiating the prefab at its position and a rotation and we're doing that every time and then on the flip side of that on each bullet every time we enter the wall trigger we're destroying it and this is our problem so let's work on a pooling fix for this so the first thing we're going to want to do we're going to want to create two classes these are going to be a pool which is going to be an individual item pool and secondly we're going to want another script which is going to be a cooler which is going to be sort of our master class we'll work on the pool first because this is going to be relatively small so this isn't going to be a mono behavior and we aren't going to need system.collections nor are we going to need to start an update so inside here we're going to need two variables and a constructor so the variables are going to be a public and we're going to use a stack you may never have used a stack before but they are extremely useful you can think of it as a list but with extra functionality and just like a list it takes in its type which is going to be game object and these are going to be all of our inactive game objects inside of our pool so we'll just set that to a new stack like we would with a list next we're going to want to create a parent game object or a reference to a parent game object so we'll just call that parent for now and that's just so we can keep all of our instantiated items in one place next the constructor which is going to be a public pool that's going to take in a game object which is going to be the parent that we want to assign to this particular pool so we'll set this dot parent equal to parent and that is actually it for our pool so we can go back over and start on our puller this is where the real magic happens now we want to make this as reusable as possible so what i'm going to do i'm going to make this a static class so we can call this from anywhere and to start off we're only going to need one variable in here and that's going to be a private static dictionary the key for this dictionary is going to be a string it's going to be our object's name and each entry into the dictionary is going to be a pool the class we've just created and this is going to be all of our available pools call that pools and again initialize it as a new dictionary and inside here we're only going to actually create two methods we're going to create a spawn method which is going to replace our instantiate and we're also going to create a dspawn which is going to replace a destroy so we'll just add those in quickly there'll be a public static void spawn and a public static void despawn so we'll work on spawn first so because this has got to replicate instantiated we're going to pass in a few parameters that are going to mirror our instantiate command those are going to be a game object we'll call that geo that's going to be a prefab that we want to instantiate vector 3 which is going to be the position that we want to instantiate it and a quaternion which is going to be the rotation so nothing too drastically different from a standard instantiate call as we can see here our instantiate is taking in a game object prefab a vector3 for the position and a quaternion for the rotation so in essence we're just mirroring that so what do we want inside spawn first of all we just want to create a reference to a game object and we'll use that if we decide to use an object from our pool rather than instantiate it secondly we want to generate a key and the way that i'm going to do this you could do this anyway you could pass in a key if you like you could use an enum the way i'm going to do it i'm going to make it all automated and i'm going to create a new string called key i'm going to set that equal to the game object that we've passed in his name and i'm going to replace that knitting well i'm going to replace clone from that name with nothing and the reason i'm going to do that is because if we passed in a bullet prefab that would be a name of bullet but because we've already instantiated it at some point during gameplay it's gonna have that bracket clone on the end of it and we don't want to do that because if we didn't replace the clone the first one that we spawned in will create its own pool under bullet and then the second third fourth any other ones are going to be under the name bullet brackets clone so this just keeps every one of them inside its own object next we want to interrogate a pool's dictionary so if pools dot contains key and then we'll just pass in the key that we've just created this means we've already got a pool ready to go next we'll do another if statement so if pools and then we'll use a key as its actual key dot inactive so a list of or a stack of inactive objects inside this particular pool if that count is equal to zero so we don't currently have any inactive versions of that object ready to be shown this is where we want to create a new one and this time we are going to be using instantiate but once enough have been instantiated we should have a healthy pool that we can just pull from as and when we like so to do that this time we're going to need to use object dot instantiate and the reason we have to do that is because we aren't inheriting from mono behavior so we need to directly access instantiate through the object class and we're just going to do it the same way as we always do we're going to instantiate a game object at the position we've passed in the rotation that we've passed in but this time we're going to append it to that pool's parent so that'll be setting the parent to pools with this key dot parent dot transform so that's going to instantiate the object wherever we tell it but it's going to have a parent which is going to match that object's current class inside the pool or parent object inside the pool rather so there we go so far we're just instantiating as normal so we'll add an else onto this so if the count isn't equal to zero that means we have an object already spawned in ready to go so this is where we're going to use our obj our game object up here so we're going to set that equal to pools use the key again dot inactive dot pop now this is where using a stack comes in really handy because what dot pop will do is it will take the top element in that stat list and return it but at the same time it'll also remove it from the stack next now that we've got uh object reference we can just set the transform dot position equal to the position that we've passed in the rotation equal to the rotation that we've passed in and then we want to set this game object to active so another way that we can see this is going to work is once the game object has been instantiated we're going to set it to active when we want it and then we're going to set it to inactive when we don't want it anymore and that's a lot better for performance than instantiating and destroying so currently we have a cord ready to go for if we have a pool ready for that object but what if we don't what if it's the first time we've pressed that button we spawn in a bullet we're obviously not going to have a pool for it at all so this is where in the else statement we can create a brand new pool and to do that we're gonna first need to create the parent object so we can create new game object call that new current and set that equal to a new game object and inside the parentheses we can actually pass in the name that we want to give to this object and i'm going to name this whatever a generated key was underscore pool in capital letters so if the object that we passed in that we're trying to create didn't have a parent and didn't have a pool we're going to create a new pool object called bullet underscore pool next we're going to want to instantiate the object because obviously we don't have a pool to take it from so that'll be again object.instantiate we're going to instantiate the game object object at the position at the rotation and this time we're going to pass in new parent dot transform as the parent object next we need to create a new pool to add into our dictionary so that'll be a pool called that new pool set that equal to a new pool and as part of the constructor for a pool as we can see we need to pass in the parent object so again we'll just pass in new parent and the final thing we need to do is add it to our dictionary which will be pools dictionary up here dot add we need to pass in the key as the key object and then the new pool that we've just created and that should be a spawn method completed so if we pop down to our d spawn again this is going to need to take in a parameter just like destroy does and that's going to be another instance of the game object that we want to in essence destroy and i'm just going to copy this because we're also going to need that key in here as well and this is going to be quite similar to the spawn method just in reverse so if our pools dot contains key key then we can just add this game object to that pool we'll get pools use the key dot inactive and this time we want to use dot push now dot push is going to do the opposite of dot pop this is going to add to the inactive stack and it's going to put it back at the top and then we'll just pass in that game object and then we're going to want to set that game object to inactive so set active false and just to keep things clean what i like to do whenever we despawn an object i like to set its transform.position equal to that way say for example we have 100 objects in we have 100 bullets and they're all deactivated so we're not shooting at all although they'd be inactive they'd be all over the map and i don't really like that obviously when you're playing the game you can't really tell but i know and it really bothers me so i just like to set it to the parent transform so we just have a nice little pile of them over somewhere in our game and the final thing that we need to do we need to cater for us despawning an object that doesn't have a pool so that'll be inside of our else statement i'm going to create a new parent object just like we did during our spot we're also going to create a new pool called that new pool set that equal to new pool and passing our new parent like we did in the spawn method next we're going to set a gameobjects.transform and then we're going to do set parent and we'll pass in new parent.transform so because the object that was already in the game didn't have pool it mustn't have a parent so now we're going to set that game object's parent to be inside the pool just so when we start using it like i said before they're all kept in the same little area and finally we need to add it to the pool so that'll be pools dot add use the key as the key and use the new pool as the pool object grab a new pool using the key dot inactive dot push so we'll put that game object into the stack and then finally set that object to inactive and that should be a puller script completed so the only thing left to do now is replace our instantiates and our destroys with spawn and despawn so inside of our bullet spawner wherever we're instantiating what i'm going to do instead i'm going to copy that just for ease but now all we need to do is call hula dot spawn and then we'll pass in exactly the same parameters as we did to our instantiates and then exactly the same down for the red bullet which is going to create its own instance so that'll be puller.spawn the red bullet this time and then inside of our bullet script instead of destroying we want to call cooler.despawn gameobject exactly like we'd call destroy so now if we go back to our game we should see if we were to press the a key that's the key that i'm using to spawn my yellow bullets we get a bullet pool with one bullet in there if i press d which is my red bullet puller i get a red bullet pool with another game object under there called red bullet if i was to press a and d again once we're going to reuse that game object it's going to set itself to active and move back down to the bottom where we want it to spawn but now for example if i press a twice we only have one bullet but the way that we've created this system is it's going to use that bullet and then instantiate a new one only if it needs one as you can see there we had two bullets and now we've got two bullets inside of our pool same for the red and then if we just haul this key down we're going to instantiate new bullets until we don't need them anymore and then it's just going to pick and choose from that bullet pool set them to active and then deactivate them again and then the same for the red so i really hope you've learned something with this i hope to see you using this in your games in the near future if you do end up using this please drop me a comment below let me know what you used it for let me know what you were pooling let me know if you found anything wrong with it actually i said this could be made better it could be expanded on but this is a really good starter for you so with that i'll see you again next week thanks for watching guys don't forget to like comment and subscribe and follow us on facebook and instagram for more bites as unity hints and tips
Info
Channel: Comp-3 Interactive
Views: 1,086
Rating: undefined out of 5
Keywords: comp3, comp3interactive, unity, unity5, unity3d, unity2d, tutorial, game, development, how, to, dev, introduction, program, programming, code, coding, csharp, c sharp, c#, javascript, games, develop, 3d, 2d, artist, programmer, editor, extension, easy, beginner, advanced, professional, course, tutor, series, multiplayer, networking, uNet, design, android, mobile, tip, tips, tricks, object pooling, pooling, pools, spawn, instantiate, destroy, performance
Id: BWt7kfmQHLk
Channel Id: undefined
Length: 19min 23sec (1163 seconds)
Published: Fri Nov 13 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.