Unity Object Pooling Made Easy: Learn to Manage Spawns Like a Pro | Unity Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video I'm going to show you how to set up an object pooling manager that can handle spawning in all the game objects particles and visual effects that you could ever want for your entire game we're going to create something both robust and very simple to use and as a bonus we'll set it up in a really organized way so that it doesn't end up clogging our hierarchy with hundreds of game objects ready let's go so here's my scene I have a player that shoots this nice Red Bull at every frame when you hold the left Mouse button and nice blue bullets when you hold the right Mouse button the red guys have gravity and the blue guys don't but they behave mostly the same apart from that we've also got some fairly underwhelming particles coming from the tip of the gun but this is just an example for a tutorial after all and when we click the middle Mouse button I parent this circle thing to the tip of the player's gun that's only there so I can show you a specific use case later on in the video so here's the code that handles all of that and there's nothing too exciting here but it's important because we're going to be replacing all of these instantiate calls from our object pooling manager that we're about to set up but these could be called from multiple scripts from multiple objects it doesn't matter we'll have one script that handles everything so with an object pool the basic idea is we are trying to replace instantiate calls as well as any corresponding destroy calls for those objects there's really nothing too complicated going on we have basically a list of objects sitting inactive and when we want to spawn something in instead of instantiating a brand new one we'll reuse one from the pool Instead This saves memory and helps us avoid garbage collection spikes in our game so this is a huge performance booster if you instantiate and destroy a lot of objects now what's cool is Unity actually has a built-in method for this and you can access it using the unityengine.pool namespace and I have a whole tutorial covering how to use that as well as showing you how to measure the performance increase you get from object pooling the built-in method is really robust and feature Rich and it's event driven it's really nice it's also not very quick to set up and it's a little bit complicated and my goal with this video is a combination of Simplicity and robustness so I'm going to set up my own object pooling system which will actually be a lot faster but if you combine my other tutorial with this one you'll have something really special okay here we go I'm going to create an empty game object called object pool manager and attach a script to it with the same name and the first thing we're going to do is set up a tiny little second class within this script and we'll call it pooled object info this is just going to hold a lookup string as well as hold a list of all our inactive game objects so you can think of one of these as one pool of objects okay each time we create a new one of these classes we'll have a new pool now we're going to set up a list of our object pools which might seem weird at first but the reason we're doing this will be clear soon enough and we'll create that in our main class and it'll be of type pooled object info and make this a static list because we're going to use it in our static method in just a second and to use class variables like this in a static method the variables also have to be static now let's create our actual spawn object method and like we said we'll make it static and let's pass in three parameters a game object a vector 3 and a quaternion let's just select the instantiate method well one of its options anyways so first we're going to search through all of our our object pools and return the one where the lookup string from the pooled object info is equal to the name of the object we want to spawn in and the way that we wrote that is not too beginner friendly because it's a Lambda expression so here is the equivalent of what that line is doing and I'll leave it here commented out just in case next if the pool doesn't exist meaning it didn't find anything so it's null then we'll create a new pool and here actually let's go ahead and set up the lookup string that this pool holds so that the next time it will actually be found then we'll add this pool to our list of pools next we want to check if there are any inactive objects in our pool meaning there is something in the pool that we can use so what we'll do is Loop through all the inactive objects in pool and if it finds one we'll assign it to this game object variable here and then stop and actually there's a much easier way to write this if we add system.link namespace up here we can accomplish the exact same thing by calling the first or default method which is a link extension method I believe I'll leave both on the screen just in case it's helpful for you so next we need to see if we found anything from our list of inactive game objects and if we didn't then we do actually need to instantiate one in because the object has to First be created before it can then be reused on the other hand if we did find something in our list of inactive game objects then we can set its position and rotation remove it from our list of inactive game objects and make the object active again and finally this method has a game object return type so let's return spawnable object all right great so that is the method we will use to replace our instantiate methods next we need a method that we'll call in place of our destroy calls so let's set up another static and we don't need a return type such as void and we'll pass in a game object parameter now we want to find a pool where its lookup string is equal to the name of the game object we're passing in but this will never return true as it is because the name of the object that we're passing in will have the word clone in brackets at the end and the lookup string won't and that is because the very first time we set up this pool we set it up before our instantiate call down here so it won't be a clone yet so I'm going to do something that feels a little gross but it works just fine we can remove the final seven characters from this object's name like this and then pass that in instead now in this case if the pool is null then we should log a warning because we're trying to release an object that hasn't been pooled so something's wrong there otherwise let's deactivate the object and add it to our pool so now we have a fully functioning object pool which creates a new object pool for every different game object we pass into it that's why we store a list of object pools to see if we already have one created for that game object we passed in and if we don't then create one to test this we need to actually replace our instantiate and Destroy calls now so we can delete these lines and now call the spawn object method from object pool manager passing in the object position and rotation just like we would in an instantiated call it also has a game object return type so we can do something like this if we wanted which would just let us easily change things for this instance of the game object and I'm going to leave this last one here just for a minute first I need to go into my bullet Behavior script and replace all of the destroy methods now this one is on a timer so I'll need to create a co-routine to handle that for the object Pooler and we'll call that in on enable so that it runs every time the object is enabled from the pool it's worth noting that on enable is called before start so I'll change this to awake and you might need to evaluate any logic that needs to be moved into on enable as well I'm going to move these methods over so to handle this for a particle system make sure that the stop action on the particle system is set to callback and we'll attach a tiny little script to our particle systems let's call it return particles to pool so by setting them to callback we can use this built-in method called on particle system stopped which will get called as soon as we stop the particle system and in there we can just call our return object to pool method so here we go let's test you can see if we left click a whole bunch of objects get spawned in but if I keep holding it they start recycling in the scene and same with our blue bullets awesome and same with our particles one little thing that would be nice though is if our hierarchy didn't get so cluttered from all of these objects so to remedy that let's go back to our object pool manager and set up an enum create as many of these as you want but think of each of these almost like a folder it's going to be an empty game object that we're going to parent our pooled objects to I'm just going to set up these two and none at the end make sure we create a static reference to this so first we need to have an actual empty game object to put all of these objects in so in our awake function let's call it setup empties method which we'll now create so for each enum type set up a corresponding private static game object so now let's create a new game object for each of those variables and we'll parent the particle effects and the game objects empties to the object pools game object okay so as soon as we start the game those empties will get created now now to actually put stuff into the correct one let's set up a static method with a game object return type called set parent object with a pool type parameter and create a switch statement in there if the type is particle systems will return the particle systems empty and if the type is a game object then return the game object and if it's none then return null so now back in our spawn object method right above where we instantiate a new game object we're going to create a parent object by passing in pool type and to do this we'll need to pass in a pool type up here as well now let's default it to none that way it's optional and we don't have to enter anything if we don't want to so now that we have a parent object let's say if it's not null we'll parent our spawnable object to it now if we go back to our spawn object calls here you can see that we don't have any errors even though we added a new parameter just a second ago and that's because we defaulted it right that makes it optional so just to test let's add this bullet to our game objects empty and this particle to our particles empty but these two will leave as is now if we run you can see these empties were created and as soon as I left click all sorts of game objects get added to that empty as well as some particles to this one but if I right click yup they're spawning into the hierarchy as expected awesome I'm just going to go ahead and add these in because I really don't like clutter now the last thing is this middle Mouse click here the reason I haven't touched that yet is because in this instantiate call we're parenting the object to the bullet spawn point and we don't have an object pull manager method that can handle only two parameters right now and we could call it like this and then manually parent it but that's a lot of work because we would have to do that every single time we want to parent something so let's create an overload method just one time which will handle this situation for us forever so back in our object pool manager let's copy this entire method and yes you can have two methods with the same name within a class they just have to have different parameters and by doing this we're actually creating what's called an overload method which means when we call this function based on the parameters that we plug in the compiler will automatically know which one of these we want to use it's really really cool so this one will work very similarly except we only need two parameters an object to spawn and a parent transform we obviously don't want to set the parent to those empties in scene because as we want to be able to set the parent ourselves and we'll update our instantiate call to reflect these new parameters as well and we have no spawn position or spawn rotation to pass in so let's just get rid of those and there we go finally let's go back here and replace that instantiate call with our new overload method which just takes in two parameters very cool this object just destroys itself after a timer which I set as a co-routine in the start method but now we'll need to change that to on enable so I'll call this in there and there we go if I middle click wait I parented it to the wrong thing hey there we go let's try that again and if I middle click then it's still appearance to the bullet spawn point it deactivates and then reactivates just like we want awesome I hope you found this video helpful guys if you did then please give it a like And subscribe for more videos like this one and if you really want to support us you can do so on patreon like all of these awesome people I want to give a very special thank you to our Hall of Fame patrons Jacob yondak zondra Kessler Darren Preen throbbing wind Fontaine weight and couch as well as our Early Access patrons zyoma Ken Waite and Mason Crow if you choose to support us on patreon you can get early access to all our YouTube videos monthly Alpha builds and more
Info
Channel: Sasquatch B Studios
Views: 12,653
Rating: undefined out of 5
Keywords: unity, unity2d, tutorial, unity tutorial, sasquatch b, sasquatch b studios, unity beginner tutorial, unity object pooling, unity increase performance, unity performance tips, unity object pool manager, object pooling, unity how to use object pooling on a particle system, unity how to, unity object pooling for all objects, object pooling for all objects, unity object pool for whole game, object pool for whole game, object pool easy, object pool
Id: 9O7uqbEe-xc
Channel Id: undefined
Length: 13min 1sec (781 seconds)
Published: Thu May 04 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.