Unity has graced us with our very own built-in object pooling! I'll show you how to get up and running with it, show you the drastic performance boost it can provide as well as lightly touch on a few of the other pool classes like the GenericPool.
Here's the base class I mentioned in the video: https://bit.ly/3nI3ubh
🔔 SUBSCRIBE: https://bit.ly/3eqG1Z6
🗨️ DISCORD: https://discord.gg/GqeHHnhHpz
✅ MORE TUTORIALS: https://www.youtube.com/tarodev
unity has just released their built-in object pooling system in version 2021 object pooling is an optimization strategy allowing you to reuse components instead of destroying and creating them each time game objects lists and classes can all be pulled to save the garbage collector's cpu cycles clearing de-allocated memory from the heap object pooling is best used when a large number of objects are being spawned and destroyed in a short period of time it's especially important when shipping to lower end devices like mobile phones and tablets let's begin so as pretty as that scene was with all the effects and sounds and uh physics and stuff they will just get in the way of this test so what i've done is i've just changed it so 10 spawn every 0.2 seconds without any effects and as soon as they collide with this floor here they just get destroyed so let me just show you how i've actually set that up so we've just got a reference to the shape prefab a the amount that we're going to spawn and then in start i'm just starting a repeating function uh where i just iterate over the spawn amount and then spawn it set it to a random position uh in a unit sphere and then i initialize it by sending in this function into the object and then the object just caches that action and then when it hits the collada it calls the action which uh destroys the object so that may seem a little bit weird like why don't we just destroy the object from within the object but uh it'll make sense in a minute so now if we press play we'll see that it's just spawning and then colliding with the ground and being destroyed but if we ramp that up to maybe 100 every 0.2 seconds we'll see that the the system is starting to stress a little bit we're tanking down to about 20 to 30 fps and if we go to our analysis tools and our profiler we will see that if we go on this spikes here we'll see that we're actually allocating uh let's see here so 39 kb of memory every 0.2 seconds 39 39 obviously that is i mean my computer's handling it okay but on a mobile device device you would be carpoot so uh let's let's fix that let's let's make this object pooled so the first thing we will do is create a private object pool and this will be of type shape because that is uh what i am using and let's just call this pool and then in start here let's make a new object pool the way pooling works is say you've got a thousand objects that you need to instantiate every second right if you're creating and destroying those objects it causes a lot of garbage that the garbage collector has to come and clean up right so instead of instantiating and destroying them all the time how about you just instantiate them once and then once they're done once you you've finished with them you disable it and then when you need another one of those objects you just grab one that you've already used and disabled and you just re-enable it right and then you put it into the position that you need it and then away you go and you just keep re-using these objects which means the memory is not constantly being allocated and deallocated which means the garbage collector doesn't need to do anything with it [Music] so that's how it works and as you can see this function takes a create function on get function a release function so these are all the actions that we need to tell unity what to do with in order to pool our object efficiently because they have no idea what object we're using we could just be using a normal game object that we just need to instantiate destroy we could be using a bullet like the bullet could potentially need to be instantiated every single time to give it a launch velocity you know could be using like boxes that need to be they could break or something and you need to rebuild them who knows what it is uh you probably shouldn't be using object pulling for that last one anyway so let's create our first required function here which is the create function so this is what unity is going to call when there are no objects in the pool available so they need to create one so uh for our create function all we're going to be doing is returning an instantiated shape prefer right that's all we need to do to create this okay so what's next it is the on get function so this is the function that is called when we ask for an object and there is one available in the pool okay so this one will take uh will it return to shape right and with this shape what are we gonna do well usually the the most basic form of object pooling is disabling and enabling so what we can do is we'll say shape dot game object set active true okay so now we've handled r on get next one is on release so this one is when we're done with the object and we need to give it back to the pool so this one will be shape and then we'll do the same but in reverse so game object set active and false and the last one here is our destroy actions so this pool will always spawn objects when we ask for them even if it's above the maximum once we've spawned it and it goes to return to the pool if the pool is already filled it will destroy the object instead so for this one it's just going to be a normal destroy function and it will put our shape game object okay so we've got a few other things to fill out here before we're done this one is collection check so basically you can save cpu cycles by turning this off and what this does is if you have an object that you've already returned to the pool if you try to return that again to the pool uh it'll cause some bad problems right so unity can handle this for you and they and basically if you try to return this object that's already been returned uh unity will say nope it's already in the pool let's just ignore it but that takes cpu cycles so if you're sure of your code and you know that will never happen you can check this to off to false sorry and you can save a little bit of cpu time okay the next one is default capacity so this one may seem simple if you know how an array works this by the way under the hood this specific object pool uses an array so if you know how an array works say you instantiate an array with a size of 10 it is allocating enough memory to store those 10 objects even if you've got no objects in that array it is still holding enough memory to store the 10. so and in addition uh resizing arrays can be expensive okay so really what you want to do with with default capacity is if you know there is only ever going to be 10 you should set it to 10. if you think there might be 11 you should set it to 11. but there's also the scenario where potentially in there could be 100 but most of the time there's only 10 okay so if you set it to 10 that's cool as long as your max size is 100 you can it will expand as it goes but that is expensive because uh say you've got 10 and then you just get one more this array now has to resize to 11 and then i might have to resize to 12 and 13 and 14 right and that takes a lot of cpu cycles whereas you probably would have been better off setting it to 100 to begin with so it didn't have to do 90 array resizes okay so play around with these numbers depending on your needs of the game you may get better results starting at small and letting it expand or starting it at the full size uh it does seem kind of silly to uh start an array at 100 and then in your map you may only use like two you know so you're still taking all the memory of 100. so i'm going to set mine to 10 for now and then max size i'm also going to set to uh actually i'll set that to 20. and then that is it that is how we create our pool we've got our create function our get function our release function and then our destroy function our collection checks which we've said false because i'm pretty sure that this code will be just fine 10 capacity and then 20 max size cool so we've created our pool and now as it would as we're benchmarking these two let's create a little serialized field here so we can change it in the editor uh use pool okay so then in our spawn function instead here uh we're instanting it instantiating it we can say are we using the cool if we are let's grab it from the pool instead of instantiating so pool dot get and it is literally that easy you you are just grabbing something from the pool otherwise let's instantiate it right because we're not using the pool and then this is why i am actually sending this uh action into the shape because i want to handle this killing logic uh in the spawner okay because it's easy for us to kind of just pass and see what's going on so just just to iterate i'm sending in this function into the shape and net so that it knows what to do once once it hits that that ground so then here we can say if we're using the pool instead of destroying it let's do shape nope let's not do that let's do pool release and then send in our shape else we will destroy it because we're not using the pool okay so if we go to our spawner and we make this 100 which i believe was what i was using for that initial test right so this is without the pull and if we go to our analysis and profiler just let it run for a little bit and then go here we will see that it is allocating 39 kb and if we go here we will see that it is all in fact from instantiating almost from instantiating all right so we can remove this uh this is 22kb of instantiating every 0.2 seconds so let's see what we can do with object pooling to improve this outcome get rid of that let's turn on cool objects and let's make the default capacity to 100 and then 800. okay so let's give that a shot and yeah if you remember last time we were tanking fps pretty bad right so now we're staying around 60 70. so that's a massive improvement just on fps if we go to uh our analysis tool here and actually it'll be better if we reset it so let's reset it and then i will pause it straight away right and so we should know that these these first ones here uh we actually are instantiating our objects aren't we so that the pool needs to fill up first so we can see here instantiate it's allocating 22 kb of garbage and that will be the same for all of these here but if we let our pool fill up to capacity so let's just give it a few seconds and then we try again here we will see that now there is no allocation happening on instantiate and we're just activating which obviously doesn't need to allocate any additional memory because we've already spawned the object all we're doing is enabling it so as you can see like my computer can handle both of these quite well but on a mobile device saving that amount of memory on allocating and de-allocating will significantly improve the performance of your game so as i talk let's just uh just maximize this as it's a little bit prettier so actually that's it's too chaotic for me too crazy let's uh reduce that down to like five yeah oh but it's so boring now that i've removed the effects and little side note which i'll probably remove in the final edit so i made this scene before i went to bed last night like right before i went to bed and my brain felt the need to imagine these falling teas all night long like i would wake up and then i would go back to sleep to more falling tears so it may look pretty to you but i just want to get this out of my face so side note so that is the standard uh object pool that unity has provided they also provide a few other options they provide a linked pool so a linked pool has a little bit of different setup but the difference between an object pool and a lint pool is object pull stores their um all the elements in an array so as i was saying before if you have a default capacity of 50 even if you've got zero items in that capacity it's still going to take the memory of the 50 elements right a linked pool uh doesn't take any memory if there's no elements in there but the downside is that it's it's more expensive to manage basically it will be more effort for the cpu to grab them from the pool and release them full from the pool so really uh you really need to decide do you favor the memory here do you need or every single little bit of memory that you can possibly pull out or do you need better management on the cpu so that's the difference there so unity has also given us a whole bunch of other pools which i'll put up on the screen now and you can go look at them individually they're all really amazing what i will do though is i'll show you one more list that i think is absolutely amazing one one more collection sorry so say you're just pretend this is the update function right um and we actually why would i pretend when i can do it so that's silly so let's just make the update function here okay say we are doing some kind of like pathfinding logic right and we we need a list in this loop so my list equals new list and this will just be like an integer list right and then we're using the list here and then it goes out of scope so uh the memory will be deallocated and the garbage collector will come and clean it up so we're creating a new list whoops we're creating a new list every single loop of update we can actually avoid the allocation and de-allocation of this i mean technically you can just create your list out here right but who knows you might have a you might have 10 lists here you do really want to just create it here to not de-allocate so what can you do about that well we can say my list now is not equal to a new list but we can do this generic pool right and this will be of type list integer and we can say get and this will just generate a list of that type right for us to use so now we can use this so let's say my list dot add and let's just say 69 right just a random number and then uh this will go instead of just letting it go out of scope we can now say generic pool of type list inch release my list so then this will release it back to the pool right and we could release 10 lists here and then next time that this is called it will grab one of the lists that we just released now obviously we would still need to clear this list right we we don't want to continue using this list we might not want 69 and then we might want another completely random number uh sorry i mean you might actually have to do this dot clear but that should be a lot better than allocating and dow locating the memory for the list itself in addition you can actually use this to uh store your own classes so let's just say this is my class and in here i'm going to have a string called hello right so now we can actually uh let's just remove this and i'll do it from scratch so my class right i need a version of the i need a version of my class and this is going to be from the generic pool of type my class and i'm going to get it and then in here i'm going to set my class dot hello equals hello and then i'm going to release it again so generic pool my class dot release my class and just to illustrate this let's set a breakpoint here attach to unity and let's play it and here we go so we've grabbed our uh first class from the pool and as you can see it is already constructed it right and there's nothing in hello let's now set hello to hello and then let's release it to the pool okay and now on the next loop of update we have now grabbed another version of my class and as you can see we've only got one in there so let's grab the one that we've already made and set to hello and we'll just keep recycling this instead of creating a new version of my class and then de-allocating it every single loop so obviously you know you need to think about resetting the object if you need to but generally it's going to be better than creating a new one and deleting it every single time i hope you enjoyed it and i hope you learned something i'm going to include a script down below of uh how i am setting up my object pooling so basically i'm creating a script and i'm deriving from it so then that turns my derived script into like a really easy object pooler where i only need to override some of these functions if i need to so check that out if you want and i will see you in the next video bye you