Using an Object pool in Godot!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome i'm your geek eric and today we're going to answer a few questions about object pulls like what are they and why should you use them would it benefit your game and if the answer to that is yes then how would you go about implementing it in your project let's jump on into it so what is an object pool well the system is actually pretty simple i'm gonna write out two different areas we're gonna have a square over here representing the object pool and over here we're gonna have a class that wants to spawn in some objects so we'll call this a wave spawner and let's put an s for now so the wave spawner is gonna want to do a few things it's going to want to ask for an object from the object pool and it's going to want that object to be returned to it so let's say the wave spawner calls a function called take object well that function will be called in the object pool and if the object does not exist then we may need to load the object into the pool now after we load those objects we need to return an object back to the wave spawner and so far you may be asking well how is this benefiting my game well now let's get into the why so this first part by itself would have been a feature game but let's say that you're spawning in with your wave spawner a pickup well whenever the pickup gets picked up or maybe it goes off screen and you want to get rid of it well the pickup can call a return function let's say return object and we can return the object back to the pool and so the next time that the wave spawner goes to spawn another pickup instead of creating that object well the object already exists in the pool so we don't have to load the object again and this does a few things it keeps us from having to load the object but whenever you delete objects and load them for that matter um there's some memory management that is being done under the hood and if you if you load or unload enough objects at a time it can actually cause your game to head like a stutter you may have seen this whenever you're going from one area of a game to another it's loading in a big chunk and basically there's a lot of games that can take advantage of this system you know a bullet held game you know so you're let me make a let me make a new a new image here so a bullet hell game you know you could be shooting a bullet and whatever it gets off the screen you can just return the bullet back to the object pool or when it hits something you can re return it back to the object pool and that way you could seemingly have an infinite number of bullets and not increase your memory usage and not incur those memory management slowdowns that i referred to earlier so if this sounds like it would be beneficial for your game let's jump on to the next segment i have a project already made on github that we can go ahead and download and all we need to do is walk through adding in the object pool to the project before we move on if this video has helped you so far maybe you enjoy game dev content like game jams or project devlogs and you may need some more tutorials in the future hey i don't know all i know is that it would help me out if you would subscribe and like this video thanks now let's get back on to it so all we need to do is go to my get repo it's gonna be linked in the description box down below next to my instagram and twitter might i add you could check those out too um we're just going to click on the screen button here code you could just click this download zip button here either works so we're just going to extract it and i'm going to open it up in my file manager let's just double click on the project file and now that we have it opened let's go into the scripts and helper and open up the object pool now we could just delete this comment here i'm just going to save it and quickly walk you through the project so it's a really simple setup you have a root world node you have a lucky sac which is just a script that holds your score we have a wave spawner that takes an array which grabs the objects from this uh array over here so let's say you had multiple objects in this array it would grab just the first object you could come in here and you could change this to a one you'll grab the second object we're just going to leave this at all zeros and what this is currently spawning is it's currently spawning the sand dollar pickup prefab and that pickup is over here under prefabs pickups sand dollar and we can see that it's just a little sand dollar with a collider on it and whenever you collide with it if it's the player that's colliding we're going to add some points and then we're going to clean up and return the object back to the object pool and that that cleanup function is in the parent so the cleanup function just calls the object pull return node and passes it itself oh uh one more thing the object pool in this project is a singleton which is located here in the auto loads right here so what that means is that no matter what scene you're in the object pool will exist in some games you may not want that for the project that this was made for it was actually better for it to be a singleton so that's what i went with so first we're going to need a few variables we're going to need a minimum amount of objects to load i currently have it set to 10. we are going to need a dictionary to hold the objects that we currently have loaded this dictionary is going to have the key which is going to be the name of the object and then the value of it is going to be all the objects that are currently in the object pool and over here we have this return queue and i'll get into that later so the first function we're going to add is the take node function now if you want if you're if you're having trouble typing it this fast just pause the video type it out and then come back for the explanation so i have a little comment here give me a short explanation of the function but let's walk through it line by line so the path is just the file path nothing special so we're going to [Music] make a new variable object that's just going to exist inside of this function we're going to check to see if the path is not already in the object pool and if it's not the object pool we're going to do another function we're going to load that object we'll get that in a second if it is in the object pool we're just going to take out one of the objects from the pool with the same path as it and we're going to after we take that object out we're going to erase the path sorry we're going to erase the object in the array and now if there's no more of that type of object in the pool we're going to erase that whole object key from the dictionary so nothing too complex we're going to return the object that we grabbed out from the object pool so next let's go through loading the object so loading the object also pretty simple all we're going to do is pass the path from the take node function to the load object function we're going to load the resource and we're going to hold that reference to the resource and for as many times as you specified up at the top we're going to make a new instance of that object and we're going to store it into the object pool now the only reason to have the difference here is because if the if the object pool is already populated all we need to do is append it and append is just adding a new element to the array at the end of the array if the object does not exist in the pool already set a new key in the dictionary and that key is going to be the path and then we're going to set one object into the array so we've already covered loading in the objects now we need to cover putting the object back in the pool and this is actually what caused the most problems for me along with memory management another good use of an object pool is that while the object's not in use well we don't need to execute any of the scripts inside the object in godot to stop execution you need to remove the object from the tree there's one catch if you try to remove an object from from the tree the tree is just this hierarchy of objects over here if you try to remove an object from the tree while collision is happening it throws a lot of errors now it doesn't necessarily crash the game although sometimes it does anyway the best thing we could do is just not remove the object while collision is happening so that's like that's one of the big use cases whenever it hits a wall or an enemy we want to put it back in the pool so the workaround that i did for this is making this return object queue if the object already exists in queue let's say that you're calling it really fast and it still exists in that queue then we don't want to add it back into the queue again having a duplicate so let's just return but if it doesn't exist in the queue then we're going to add it to the queue and a good way to not try to remove it from the queue during collision is to is to in the process we're gonna clean that return queue so the last function of this object pool is to clean the return queue while the return queue is greater than zero so just to walk you through this part while the return queue length is not zero we're going to pop the front object in the array and what that does is it says hey who's the front object raise its hand you pick it up you take it out of that array and it returns it and you could then store it into a local variable inside the function so now we have that first object no longer existing in the array we check to see if the object's null this is this is just some error handling potentially a null object can get in there and cause problems but we're just going to say hey if it's a null object return don't worry about it then we get the parent of the object again if the parents know this is more error handling than when we return if the parent's not null then we remove the object from being a child of the parent and what that does is it stops the execution of future collision any scripts you have on that object it stops the execution of those scripts that way you save on some of those cpu resources it also uh takes it out of you know visual space and so you're saving on some gpu resources as well so after we've removed the object from the tree we're going to check to see if our object pool contains a key for the object if it does we append it to that list and if it doesn't well we just make a new a new entry in our dictionary and we add the object to it so let's let's check this out let's let's see if it works so i'm just gonna pull up the debugger over here we're gonna track the objects and as you can see we can pick up some pickups it it's just spawning in more and more waves the nice thing about this script is as you need more objects like for example if i well i may not be able to do this again but if i need more more of these pickups on the screen we'll just add more objects to the object pool so you know you can see this is a pretty flat graph again this is whenever we need more objects on the screen it bumped it up this is a this is a pretty flat graph let me demonstrate to you what happens if we were using a more conventional system where when the pickup's picked up it gets deleted or when it goes off screen it gets deleted so to demonstrate that we just go into the pickup instead of that nice cleanup function we do cue free and what q3 does is after collision it removes it from the tree and deletes the object let's do cue free there so that's whenever it gets picked up what about the off-screen part let's see okay so on-screen exit we're [Music] also going to take that out and put q free i could have just put that in the cleanup function let's check out that graph again so let's hit play and go to monitor show the objects then we can get over here and if we start collecting a bunch of objects this game is simple enough that you're not going to see the slowdown in its current form but potentially if you expanded this game and it was running on you know maybe like an older phone or something you would you would be seeing some slowdowns in these parts of the graph where it's deleting and having to create projects and really that's that's just wasted performance that you could be using on something else like you know let's say that you're not trying to run it on old hardware but you're trying to squeeze as much performance out of the computer that you're that you are using it on and this is if you're if you're not using an object pool in this case you're leaving performance on the table so i hope this video was useful again if it was hey that subscribe button's there there's a little bell next to it you give it a little ring if you have any suggestions on how i should do tutorials in the future please drop them in the comments section down below if you have any experiences of how an object pool helped your game or a project that you're working on that you're going to add it to drop those in the description my description comment section and i'll all respond and we'll we'll have a good conversation down there thanks for watching catch you guys next time bye
Info
Channel: yourgeekeric
Views: 2,488
Rating: undefined out of 5
Keywords: Godot, Object Pool, Godot Object Pool
Id: UZ3W53roZ7w
Channel Id: undefined
Length: 21min 12sec (1272 seconds)
Published: Tue Dec 29 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.